From b5b308c99d8d73ac7218efd82c839a00348454b5 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 13 Jun 2024 08:29:22 +0200 Subject: [PATCH 01/85] fix: `ThemeProvider` properly resync the theme (#5363) * Fix theme internals * Also fix the animation --- .../data_models/tagline/tagline_provider.dart | 6 ++-- .../lib/pages/scan/scan_tagline.dart | 6 ++-- .../lib/resources/app_animations.dart | 2 +- .../smooth_app/lib/themes/theme_provider.dart | 28 ++++++++++++++++--- .../lib/widgets/smooth_product_carousel.dart | 16 ++++------- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart b/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart index d1f3a684c18..f80f1148f16 100644 --- a/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart +++ b/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'dart:isolate'; import 'package:collection/collection.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; import 'package:http/http.dart' as http; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; @@ -63,9 +63,9 @@ class TagLineProvider extends ChangeNotifier { void _emit(TagLineState state) { _state = state; - try { + WidgetsBinding.instance.addPostFrameCallback((_) { notifyListeners(); - } catch (_) {} + }); } TagLineState get state => _state; diff --git a/packages/smooth_app/lib/pages/scan/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/scan_tagline.dart index 1a906e818b3..8fabda2f8a8 100644 --- a/packages/smooth_app/lib/pages/scan/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/scan_tagline.dart @@ -112,7 +112,7 @@ class _ScanTagLineContentState extends State<_ScanTagLineContent> { DecoratedBox( decoration: BoxDecoration( color: currentNews.style?.titleBackground ?? - (themeProvider.isLightTheme + (!themeProvider.isDarkMode(context) ? theme.primarySemiDark : theme.primaryBlack), borderRadius: const BorderRadiusDirectional.only( @@ -137,7 +137,7 @@ class _ScanTagLineContentState extends State<_ScanTagLineContent> { child: DecoratedBox( decoration: BoxDecoration( color: currentNews.style?.contentBackgroundColor ?? - (themeProvider.isLightTheme + (!themeProvider.isDarkMode(context) ? theme.primaryMedium : theme.primaryDark), borderRadius: const BorderRadiusDirectional.only( @@ -253,7 +253,7 @@ class _TagLineContentBody extends StatelessWidget { text: message, textStyle: TextStyle( color: textColor ?? - (themeProvider.isLightTheme + (!themeProvider.isDarkMode(context) ? theme.primarySemiDark : theme.primaryLight), ), diff --git a/packages/smooth_app/lib/resources/app_animations.dart b/packages/smooth_app/lib/resources/app_animations.dart index d568adff803..2b8a602ab10 100644 --- a/packages/smooth_app/lib/resources/app_animations.dart +++ b/packages/smooth_app/lib/resources/app_animations.dart @@ -169,7 +169,7 @@ class _SearchEyeAnimationState extends State { @override Widget build(BuildContext context) { final double size = widget.size ?? IconTheme.of(context).size ?? 24.0; - final bool lightTheme = context.watch().isLightTheme; + final bool lightTheme = context.watch().isDarkMode(context); return ExcludeSemantics( child: SizedBox( diff --git a/packages/smooth_app/lib/themes/theme_provider.dart b/packages/smooth_app/lib/themes/theme_provider.dart index 3f0626aee01..0bb268f8d89 100644 --- a/packages/smooth_app/lib/themes/theme_provider.dart +++ b/packages/smooth_app/lib/themes/theme_provider.dart @@ -7,15 +7,28 @@ const String THEME_DARK = 'Dark'; const String THEME_AMOLED = 'AMOLED'; class ThemeProvider with ChangeNotifier { - ThemeProvider(this._userPreferences); + ThemeProvider(this._userPreferences) + : _theme = _userPreferences.currentTheme { + _userPreferences.addListener(_onPreferencesChanged); + } final UserPreferences _userPreferences; // The onboarding needs the light mode. bool _forceLight = false; - String get currentTheme => - _forceLight ? THEME_LIGHT : _userPreferences.currentTheme; + // Local cache for [_userPreferences.currentTheme] + String _theme; + + void _onPreferencesChanged() { + final String newTheme = _userPreferences.currentTheme; + if (newTheme != _theme) { + _theme = newTheme; + notifyListeners(); + } + } + + String get currentTheme => _forceLight ? THEME_LIGHT : _theme; void setOnboardingComplete(final bool onboardingComplete) { _forceLight = !onboardingComplete; @@ -53,6 +66,13 @@ class ThemeProvider with ChangeNotifier { } bool isDarkMode(BuildContext context) { - return MediaQuery.platformBrightnessOf(context) == Brightness.dark; + return currentThemeMode != ThemeMode.light && + MediaQuery.platformBrightnessOf(context) == Brightness.dark; + } + + @override + void dispose() { + _userPreferences.removeListener(_onPreferencesChanged); + super.dispose(); } } diff --git a/packages/smooth_app/lib/widgets/smooth_product_carousel.dart b/packages/smooth_app/lib/widgets/smooth_product_carousel.dart index af7695ae3f2..d5d806235c0 100644 --- a/packages/smooth_app/lib/widgets/smooth_product_carousel.dart +++ b/packages/smooth_app/lib/widgets/smooth_product_carousel.dart @@ -263,12 +263,10 @@ class _SearchCard extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations localizations = AppLocalizations.of(context); - final ThemeProvider themeProvider = context.watch(); + final bool lightTheme = !context.watch().isDarkMode(context); final Widget widget = SmoothCard( - color: themeProvider.isLightTheme - ? Colors.grey.withOpacity(0.1) - : Colors.black, + color: lightTheme ? Colors.grey.withOpacity(0.1) : Colors.black, padding: const EdgeInsets.symmetric( vertical: MEDIUM_SPACE, horizontal: LARGE_SPACE, @@ -281,7 +279,7 @@ class _SearchCard extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ SvgPicture.asset( - Theme.of(context).brightness == Brightness.light + lightTheme ? 'assets/app/logo_text_black.svg' : 'assets/app/logo_text_white.svg', semanticsLabel: localizations.homepage_main_card_logo_description, @@ -317,9 +315,9 @@ class _SearchBar extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations localizations = AppLocalizations.of(context); - final ThemeProvider themeProvider = context.watch(); final SmoothColorsThemeExtension theme = Theme.of(context).extension()!; + final bool lightTheme = !context.watch().isDarkMode(context); return SizedBox( height: SEARCH_BAR_HEIGHT, @@ -329,7 +327,7 @@ class _SearchBar extends StatelessWidget { child: Ink( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30.0), - color: themeProvider.isLightTheme ? Colors.white : theme.greyDark, + color: lightTheme ? Colors.white : theme.greyDark, border: Border.all(color: theme.primaryBlack), ), child: Row( @@ -347,9 +345,7 @@ class _SearchBar extends StatelessWidget { maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - color: themeProvider.isLightTheme - ? Colors.black - : Colors.white, + color: lightTheme ? Colors.black : Colors.white, ), ), ), From 08071d273b048753b1a1c1d9ada51d224c60873c Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 13 Jun 2024 08:53:14 +0200 Subject: [PATCH 02/85] feat: Custom domain + environment support for the TagLine (#5364) * Support custom domain + env for the TagLine * Update packages/smooth_app/lib/data_models/tagline/tagline_provider.dart --------- Co-authored-by: Pierre Slamich --- .../data_models/tagline/tagline_provider.dart | 66 +++++++- packages/smooth_app/lib/main.dart | 22 +-- .../smooth_app/lib/pages/scan/scan_page.dart | 147 +++++++++--------- 3 files changed, 145 insertions(+), 90 deletions(-) diff --git a/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart b/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart index f80f1148f16..6489cb8ab54 100644 --- a/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart +++ b/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart @@ -5,10 +5,14 @@ import 'dart:isolate'; import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart'; import 'package:http/http.dart' as http; +import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/data_models/tagline/tagline_model.dart'; +import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/services/smooth_services.dart'; part 'tagline_json.dart'; @@ -19,10 +23,21 @@ part 'tagline_json.dart'; /// To be notified of changes, listen to this [ChangeNotifier] and more /// particularly to the [state] property class TagLineProvider extends ChangeNotifier { - TagLineProvider() : _state = const TagLineLoading() { + TagLineProvider(UserPreferences preferences) + : _state = const TagLineLoading(), + _preferences = preferences, + _domain = preferences.getDevModeString( + UserPreferencesDevMode.userPreferencesTestEnvDomain) ?? + '', + _prodEnv = preferences + .getFlag(UserPreferencesDevMode.userPreferencesFlagProd) ?? + true { + _preferences.addListener(_onPreferencesChanged); loadTagLine(); } + final UserPreferences _preferences; + TagLineState _state; bool get hasContent => _state is TagLineLoaded; @@ -56,8 +71,10 @@ class TagLineProvider extends ChangeNotifier { () => _parseJSONAndGetLocalizedContent(jsonString!, locale)); if (tagLine == null) { _emit(const TagLineError('Unable to parse the JSON file')); + Logs.e('Unable to parse the Tagline file'); } else { _emit(TagLineLoaded(tagLine)); + Logs.i('TagLine reloaded'); } } @@ -83,12 +100,25 @@ class TagLineProvider extends ChangeNotifier { } } - /// API URL: [https://world.openfoodfacts.org/files/tagline-off-ios-v3.json] - /// or [https://world.openfoodfacts.org/files/tagline-off-android-v3.json] + /// API URL: [https://world.openfoodfacts.[org/net]/resources/files/tagline-off-ios-v3.json] + /// or [https://world.openfoodfacts.[org/net]/resources/files/tagline-off-android-v3.json] Future _fetchTagLine() async { try { - final http.Response response = - await http.get(Uri.https('world.openfoodfacts.org', _tagLineUrl)); + final UriProductHelper uriProductHelper = ProductQuery.uriProductHelper; + final Map headers = {}; + final Uri uri = uriProductHelper.getUri(path: _tagLineUrl); + + if (uriProductHelper.userInfoForPatch != null) { + headers['Authorization'] = + 'Basic ${base64Encode(utf8.encode(uriProductHelper.userInfoForPatch!))}'; + } + + final http.Response response = await http.get(uri, headers: headers); + + if (response.statusCode == 404) { + Logs.e("Remote file $uri doesn't exist!"); + throw Exception('Incorrect URL= $uri'); + } final String json = const Utf8Decoder().convert(response.bodyBytes); @@ -125,6 +155,32 @@ class TagLineProvider extends ChangeNotifier { file .lastModifiedSync() .isAfter(DateTime.now().add(const Duration(days: -1))); + + bool? _prodEnv; + String? _domain; + + /// [ProductQuery.uriProductHelper] is not synced yet, + /// so we have to check it manually + Future _onPreferencesChanged() async { + final String domain = _preferences.getDevModeString( + UserPreferencesDevMode.userPreferencesTestEnvDomain) ?? + ''; + final bool prodEnv = + _preferences.getFlag(UserPreferencesDevMode.userPreferencesFlagProd) ?? + true; + + if (domain != _domain || prodEnv != _prodEnv) { + _domain = domain; + _prodEnv = prodEnv; + loadTagLine(forceUpdate: true); + } + } + + @override + void dispose() { + _preferences.removeListener(_onPreferencesChanged); + super.dispose(); + } } sealed class TagLineState { diff --git a/packages/smooth_app/lib/main.dart b/packages/smooth_app/lib/main.dart index 76f7ab41574..79d451e26f8 100644 --- a/packages/smooth_app/lib/main.dart +++ b/packages/smooth_app/lib/main.dart @@ -106,7 +106,6 @@ late TextContrastProvider _textContrastProvider; final ContinuousScanModel _continuousScanModel = ContinuousScanModel(); final PermissionListener _permissionListener = PermissionListener(permission: Permission.camera); -final TagLineProvider _tagLineProvider = TagLineProvider(); bool _init1done = false; // Had to split init in 2 methods, for test/screenshots reasons. @@ -224,15 +223,20 @@ class _SmoothAppState extends State { provide(_userManagementProvider), provide(_continuousScanModel), provide(_permissionListener), - provide(_tagLineProvider, lazy: true), ], - child: AnimationsLoader( - child: AppNavigator( - observers: [ - SentryNavigatorObserver(), - matomoObserver, - ], - child: Builder(builder: _buildApp), + child: ChangeNotifierProvider( + create: (BuildContext context) => TagLineProvider( + context.read(), + ), + lazy: true, + child: AnimationsLoader( + child: AppNavigator( + observers: [ + SentryNavigatorObserver(), + matomoObserver, + ], + child: Builder(builder: _buildApp), + ), ), ), ); diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index d352c36efc6..500972deb9c 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -8,7 +8,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; -import 'package:smooth_app/data_models/tagline/tagline_provider.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; @@ -61,88 +60,84 @@ class _ScanPageState extends State { Theme.of(context).brightness == Brightness.light && Platform.isIOS ? Brightness.dark : null, - body: ChangeNotifierProvider( - lazy: true, - create: (_) => TagLineProvider(), - child: Container( - color: Colors.white, - child: SafeArea( - child: Container( - color: Theme.of(context).colorScheme.background, - child: Column( - children: [ - if (hasACamera) - Expanded( - flex: 100 - _carouselHeightPct, - child: Consumer( - builder: ( - BuildContext context, - PermissionListener listener, - _, - ) { - switch (listener.value.status) { - case DevicePermissionStatus.checking: - return EMPTY_WIDGET; - case DevicePermissionStatus.granted: - // TODO(m123): change - return const CameraScannerPage(); - default: - return const _PermissionDeniedCard(); - } - }, - ), - ), + body: Container( + color: Colors.white, + child: SafeArea( + child: Container( + color: Theme.of(context).colorScheme.background, + child: Column( + children: [ + if (hasACamera) Expanded( - flex: _carouselHeightPct, - child: Padding( - padding: const EdgeInsetsDirectional.only(bottom: 10.0), - child: SmoothProductCarousel( - containSearchCard: true, - onPageChangedTo: (int page, String? barcode) async { - if (barcode == null) { - // We only notify for new products - return; - } + flex: 100 - _carouselHeightPct, + child: Consumer( + builder: ( + BuildContext context, + PermissionListener listener, + _, + ) { + switch (listener.value.status) { + case DevicePermissionStatus.checking: + return EMPTY_WIDGET; + case DevicePermissionStatus.granted: + // TODO(m123): change + return const CameraScannerPage(); + default: + return const _PermissionDeniedCard(); + } + }, + ), + ), + Expanded( + flex: _carouselHeightPct, + child: Padding( + padding: const EdgeInsetsDirectional.only(bottom: 10.0), + child: SmoothProductCarousel( + containSearchCard: true, + onPageChangedTo: (int page, String? barcode) async { + if (barcode == null) { + // We only notify for new products + return; + } - // Both are Future methods, but it doesn't matter to wait here - SmoothHapticFeedback.lightNotification(); + // Both are Future methods, but it doesn't matter to wait here + SmoothHapticFeedback.lightNotification(); - if (_userPreferences.playCameraSound) { - await _initSoundManagerIfNecessary(); - await _musicPlayer!.stop(); - await _musicPlayer!.play( - AssetSource('audio/beep.wav'), - volume: 0.5, - ctx: const AudioContext( - android: AudioContextAndroid( - isSpeakerphoneOn: false, - stayAwake: false, - contentType: AndroidContentType.sonification, - usageType: AndroidUsageType.notification, - audioFocus: - AndroidAudioFocus.gainTransientMayDuck, - ), - iOS: AudioContextIOS( - category: AVAudioSessionCategory.soloAmbient, - options: [ - AVAudioSessionOptions.mixWithOthers, - ], - ), + if (_userPreferences.playCameraSound) { + await _initSoundManagerIfNecessary(); + await _musicPlayer!.stop(); + await _musicPlayer!.play( + AssetSource('audio/beep.wav'), + volume: 0.5, + ctx: const AudioContext( + android: AudioContextAndroid( + isSpeakerphoneOn: false, + stayAwake: false, + contentType: AndroidContentType.sonification, + usageType: AndroidUsageType.notification, + audioFocus: + AndroidAudioFocus.gainTransientMayDuck, ), - ); - } - - SemanticsService.announce( - appLocalizations.scan_announce_new_barcode(barcode), - direction, - assertiveness: Assertiveness.assertive, + iOS: AudioContextIOS( + category: AVAudioSessionCategory.soloAmbient, + options: [ + AVAudioSessionOptions.mixWithOthers, + ], + ), + ), ); - }, - ), + } + + SemanticsService.announce( + appLocalizations.scan_announce_new_barcode(barcode), + direction, + assertiveness: Assertiveness.assertive, + ); + }, ), ), - ], - ), + ), + ], ), ), ), From f5973da76964a31a498e1e546f8566948b3b44fa Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 13 Jun 2024 11:52:22 +0200 Subject: [PATCH 03/85] fix: Guide: Rewrite newline character from translations (#5365) --- packages/smooth_app/lib/helpers/strings_helper.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/smooth_app/lib/helpers/strings_helper.dart b/packages/smooth_app/lib/helpers/strings_helper.dart index 962a0ad19cc..48f631ff09e 100644 --- a/packages/smooth_app/lib/helpers/strings_helper.dart +++ b/packages/smooth_app/lib/helpers/strings_helper.dart @@ -58,6 +58,8 @@ class TextHelper { required TextStyle? defaultStyle, required TextStyle? highlightedStyle, }) { + text = text.replaceAll(r'\n', '\n'); + final Iterable highlightedParts = RegExp('$symbol[^$symbol]+$symbol').allMatches(text); @@ -108,7 +110,6 @@ class FormattedText extends StatelessWidget { @override Widget build(BuildContext context) { final TextStyle defaultTextStyle = textStyle ?? const TextStyle(); - return RichText( text: TextSpan( style: DefaultTextStyle.of(context).style, From 7bf53e894dba429dc9e7ba8d0f2dca4176fd6181 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Fri, 14 Jun 2024 12:05:41 +0200 Subject: [PATCH 04/85] feat: 5204 - preliminary step for multi-product price addition (#5367) * feat: 5204 - preliminary conceptual step New files: * `price_amount_model.dart`: Model for the price of a single product. * `price_meta_product.dart`: Meta version of a product, coming from OFF or from Prices. * `price_product_search_page.dart`: Product Search Page, for Prices. * `price_product_list_tile.dart`: Displays a meta product with an action button, as a ListTile. Impacted files: * `app_en.arb`: added 2 labels for the new "price product search" page * `app_fr.arb`: added 2 labels for the new "price product search" page * `edit_product_page.dart`: minor refactoring * `get_prices_model.dart`: minor refactoring * `price_amount_card.dart`: minor refactoring * `price_amount_field.dart`: minor refactoring * `price_count_widget.dart`: minor refactoring * `price_model.dart`: moved product amount code to new class `PriceAmountModel` * `price_product_widget.dart`: unrelated UI refactoring * `prices_card.dart`: minor refactoring * `product_price_add_page.dart`: minor refactoring * No "edit" button for product --- packages/smooth_app/lib/l10n/app_en.arb | 10 + packages/smooth_app/lib/l10n/app_fr.arb | 10 + .../lib/pages/prices/get_prices_model.dart | 34 +--- .../lib/pages/prices/price_amount_card.dart | 26 ++- .../lib/pages/prices/price_amount_field.dart | 8 +- .../lib/pages/prices/price_amount_model.dart | 48 +++++ .../lib/pages/prices/price_count_widget.dart | 30 ++- .../lib/pages/prices/price_meta_product.dart | 25 +++ .../lib/pages/prices/price_model.dart | 58 ++---- .../pages/prices/price_product_list_tile.dart | 67 +++++++ .../prices/price_product_search_page.dart | 178 ++++++++++++++++++ .../pages/prices/price_product_widget.dart | 121 ++++++------ .../lib/pages/prices/prices_card.dart | 5 +- .../pages/prices/product_price_add_page.dart | 119 +++++------- .../lib/pages/product/edit_product_page.dart | 3 +- 15 files changed, 499 insertions(+), 243 deletions(-) create mode 100644 packages/smooth_app/lib/pages/prices/price_amount_model.dart create mode 100644 packages/smooth_app/lib/pages/prices/price_meta_product.dart create mode 100644 packages/smooth_app/lib/pages/prices/price_product_list_tile.dart create mode 100644 packages/smooth_app/lib/pages/prices/price_product_search_page.dart diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 3d48a96bd50..62fe2061924 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1676,6 +1676,16 @@ "prices_generic_title": "Prices", "prices_add_a_price": "Add a price", "prices_send_the_price": "Send the price", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 49191b1a4ab..8a0abe7c476 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1676,6 +1676,16 @@ "prices_generic_title": "Prix", "prices_add_a_price": "Ajouter un prix", "prices_send_the_price": "Envoyer le prix", + "prices_barcode_search_title": "Recherche de produit", + "prices_barcode_search_running": "À la recherche de {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, "prices_view_prices": "Voir les prix", "prices_list_length_one_page": "{count,plural, =0{Aucun prix} =1{Un seul prix} other{Tous les {count} prix}}", "@prices_list_length_one_page": { diff --git a/packages/smooth_app/lib/pages/prices/get_prices_model.dart b/packages/smooth_app/lib/pages/prices/get_prices_model.dart index 5caa7ae2f52..726b2fee50e 100644 --- a/packages/smooth_app/lib/pages/prices/get_prices_model.dart +++ b/packages/smooth_app/lib/pages/prices/get_prices_model.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; -import 'package:smooth_app/helpers/product_cards_helper.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/product_price_add_page.dart'; import 'package:smooth_app/query/product_query.dart'; @@ -20,18 +20,15 @@ class GetPricesModel { /// Gets latest prices for a product. factory GetPricesModel.product({ - required final Product product, + required final PriceMetaProduct product, required final BuildContext context, }) => GetPricesModel( - parameters: _getProductPricesParameters(product.barcode!), + parameters: _getProductPricesParameters(product.barcode), displayOwner: true, displayProduct: false, - uri: _getProductPricesUri(product.barcode!), - title: getProductNameAndBrands( - product, - AppLocalizations.of(context), - ), + uri: _getProductPricesUri(product.barcode), + title: product.getName(AppLocalizations.of(context)), subtitle: product.barcode, addButton: () async => ProductPriceAddPage.showProductPage( context: context, @@ -40,27 +37,6 @@ class GetPricesModel { enableCountButton: false, ); - /// Gets latest prices for a barcode. - factory GetPricesModel.barcode({ - required final String barcode, - required final String name, - required final BuildContext context, - }) => - GetPricesModel( - parameters: _getProductPricesParameters(barcode), - displayOwner: true, - displayProduct: false, - uri: _getProductPricesUri(barcode), - title: name, - subtitle: barcode, - addButton: () async => ProductPriceAddPage.showBarcodePage( - context: context, - barcode: barcode, - title: name, - ), - enableCountButton: false, - ); - static GetPricesParameters _getProductPricesParameters( final String barcode, ) => diff --git a/packages/smooth_app/lib/pages/prices/price_amount_card.dart b/packages/smooth_app/lib/pages/prices/price_amount_card.dart index bb59826b99d..7ffc5ad9e7a 100644 --- a/packages/smooth_app/lib/pages/prices/price_amount_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_amount_card.dart @@ -1,15 +1,17 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:provider/provider.dart'; import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/prices/price_amount_field.dart'; -import 'package:smooth_app/pages/prices/price_model.dart'; +import 'package:smooth_app/pages/prices/price_amount_model.dart'; +import 'package:smooth_app/pages/prices/price_product_list_tile.dart'; /// Card that displays the amounts (discounted or not) for price adding. class PriceAmountCard extends StatefulWidget { - const PriceAmountCard(); + const PriceAmountCard(this.model); + + final PriceAmountModel model; @override State createState() => _PriceAmountCardState(); @@ -22,16 +24,22 @@ class _PriceAmountCardState extends State { @override Widget build(BuildContext context) { - final PriceModel model = context.watch(); final AppLocalizations appLocalizations = AppLocalizations.of(context); return SmoothCard( child: Column( children: [ Text(appLocalizations.prices_amount_subtitle), + PriceProductListTile( + product: widget.model.product, + ), SmoothLargeButtonWithIcon( - icon: model.promo ? Icons.check_box : Icons.check_box_outline_blank, + icon: widget.model.promo + ? Icons.check_box + : Icons.check_box_outline_blank, text: appLocalizations.prices_amount_is_discounted, - onPressed: () => model.promo = !model.promo, + onPressed: () => setState( + () => widget.model.promo = !widget.model.promo, + ), ), const SizedBox(height: SMALL_SPACE), LayoutBuilder( @@ -46,10 +54,10 @@ class _PriceAmountCardState extends State { child: PriceAmountField( controller: _controllerPaid, isPaidPrice: true, - model: model, + model: widget.model, ), ); - if (!model.promo) { + if (!widget.model.promo) { return Align( alignment: Alignment.centerLeft, child: columnPaid, @@ -60,7 +68,7 @@ class _PriceAmountCardState extends State { child: PriceAmountField( controller: _controllerWithoutDiscount, isPaidPrice: false, - model: model, + model: widget.model, ), ); return Row( diff --git a/packages/smooth_app/lib/pages/prices/price_amount_field.dart b/packages/smooth_app/lib/pages/prices/price_amount_field.dart index 345b180052c..a45093b5014 100644 --- a/packages/smooth_app/lib/pages/prices/price_amount_field.dart +++ b/packages/smooth_app/lib/pages/prices/price_amount_field.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; -import 'package:smooth_app/pages/prices/price_model.dart'; +import 'package:smooth_app/pages/prices/price_amount_model.dart'; /// Text field that displays a single amount for price adding. class PriceAmountField extends StatelessWidget { @@ -11,7 +11,7 @@ class PriceAmountField extends StatelessWidget { required this.controller, }); - final PriceModel model; + final PriceAmountModel model; final bool isPaidPrice; final TextEditingController controller; @@ -46,7 +46,7 @@ class PriceAmountField extends StatelessWidget { if (value == null || value.isEmpty) { return appLocalizations.prices_amount_price_mandatory; } - final double? doubleValue = model.validateDouble(value); + final double? doubleValue = PriceAmountModel.validateDouble(value); if (doubleValue == null) { return appLocalizations.prices_amount_price_incorrect; } @@ -57,7 +57,7 @@ class PriceAmountField extends StatelessWidget { if (value == null || value.isEmpty) { return null; } - final double? doubleValue = model.validateDouble(value); + final double? doubleValue = PriceAmountModel.validateDouble(value); if (doubleValue == null) { return appLocalizations.prices_amount_price_incorrect; } diff --git a/packages/smooth_app/lib/pages/prices/price_amount_model.dart b/packages/smooth_app/lib/pages/prices/price_amount_model.dart new file mode 100644 index 00000000000..32ec3d100ef --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_amount_model.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; + +/// Model for the price of a single product. +class PriceAmountModel { + PriceAmountModel({ + required this.product, + }); + + PriceMetaProduct product; + + String _paidPrice = ''; + String _priceWithoutDiscount = ''; + + set paidPrice(final String value) => _paidPrice = value; + + set priceWithoutDiscount(final String value) => _priceWithoutDiscount = value; + + late double _checkedPaidPrice; + double? _checkedPriceWithoutDiscount; + + double get checkedPaidPrice => _checkedPaidPrice; + + double? get checkedPriceWithoutDiscount => _checkedPriceWithoutDiscount; + + bool promo = false; + + static double? validateDouble(final String value) => + double.tryParse(value) ?? + double.tryParse( + value.replaceAll(',', '.'), + ); + + String? checkParameters(final BuildContext context) { + _checkedPaidPrice = validateDouble(_paidPrice)!; + _checkedPriceWithoutDiscount = null; + if (promo) { + if (_priceWithoutDiscount.isNotEmpty) { + _checkedPriceWithoutDiscount = validateDouble(_priceWithoutDiscount); + if (_checkedPriceWithoutDiscount == null) { + return AppLocalizations.of(context).prices_amount_price_incorrect; + } + } + } + return null; + } +} diff --git a/packages/smooth_app/lib/pages/prices/price_count_widget.dart b/packages/smooth_app/lib/pages/prices/price_count_widget.dart index 85e9c0125a2..a1604d978e5 100644 --- a/packages/smooth_app/lib/pages/prices/price_count_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_count_widget.dart @@ -5,23 +5,19 @@ import 'package:smooth_app/database/dao_product.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/price_button.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; /// Price Count display. class PriceCountWidget extends StatelessWidget { const PriceCountWidget( this.count, { - required this.barcode, - required this.name, + required this.priceProduct, required this.enableCountButton, }); final int count; - final String barcode; - - /// Product name to display in case we have only the barcode, not the product. - final String name; - + final PriceProduct priceProduct; final bool enableCountButton; @override @@ -31,24 +27,20 @@ class PriceCountWidget extends StatelessWidget { : () async { final LocalDatabase localDatabase = context.read(); - final Product? product = - await DaoProduct(localDatabase).get(barcode); + final Product? newProduct = + await DaoProduct(localDatabase).get(priceProduct.code); if (!context.mounted) { return; } return Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => PricesPage( - product != null - ? GetPricesModel.product( - product: product, - context: context, - ) - : GetPricesModel.barcode( - barcode: barcode, - name: name, - context: context, - ), + GetPricesModel.product( + product: newProduct != null + ? PriceMetaProduct.product(newProduct) + : PriceMetaProduct.priceProduct(priceProduct), + context: context, + ), ), ), ); diff --git a/packages/smooth_app/lib/pages/prices/price_meta_product.dart b/packages/smooth_app/lib/pages/prices/price_meta_product.dart new file mode 100644 index 00000000000..31af34fed44 --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_meta_product.dart @@ -0,0 +1,25 @@ +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/helpers/product_cards_helper.dart'; + +/// Meta version of a product, coming from OFF or from Prices. +class PriceMetaProduct { + PriceMetaProduct.product(Product this.product) : priceProduct = null; + PriceMetaProduct.priceProduct(PriceProduct this.priceProduct) + : product = null; + + final Product? product; + final PriceProduct? priceProduct; + + String get barcode => + product != null ? product!.barcode! : priceProduct!.code; + + String getName(final AppLocalizations appLocalizations) => product != null + ? getProductNameAndBrands( + product!, + appLocalizations, + ) + : priceProduct!.name ?? priceProduct!.code; + + String? get imageUrl => product != null ? null : priceProduct!.imageURL; +} diff --git a/packages/smooth_app/lib/pages/prices/price_model.dart b/packages/smooth_app/lib/pages/prices/price_model.dart index 5815178c7da..b804400fb74 100644 --- a/packages/smooth_app/lib/pages/prices/price_model.dart +++ b/packages/smooth_app/lib/pages/prices/price_model.dart @@ -7,18 +7,21 @@ import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/pages/crop_parameters.dart'; import 'package:smooth_app/pages/locations/osm_location.dart'; import 'package:smooth_app/pages/onboarding/currency_selector_helper.dart'; +import 'package:smooth_app/pages/prices/price_amount_model.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; /// Price Model (checks and background task call) for price adding. class PriceModel with ChangeNotifier { PriceModel({ required final ProofType proofType, required final List locations, - required this.barcode, + required final PriceMetaProduct product, }) : _proofType = proofType, _date = DateTime.now(), - _locations = locations; + _locations = locations, + priceAmountModel = PriceAmountModel(product: product); - final String barcode; + final PriceAmountModel priceAmountModel; CropParameters? _cropParameters; @@ -61,33 +64,10 @@ class PriceModel with ChangeNotifier { OsmLocation? get location => _locations.firstOrNull; - bool _promo = false; - - bool get promo => _promo; - - set promo(final bool promo) { - _promo = promo; - notifyListeners(); - } - - String _paidPrice = ''; - String _priceWithoutDiscount = ''; - - set paidPrice(final String value) => _paidPrice = value; - set priceWithoutDiscount(final String value) => _priceWithoutDiscount = value; - late Currency _checkedCurrency; - late double _checkedPaidPrice; - double? _checkedPriceWithoutDiscount; - - double? validateDouble(final String value) => - double.tryParse(value) ?? - double.tryParse( - value.replaceAll(',', '.'), - ); /// Returns the error message of the parameter check, or null if OK. - Future checkParameters(final BuildContext context) async { + String? checkParameters(final BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); if (cropParameters == null) { return appLocalizations.prices_proof_mandatory; @@ -97,15 +77,9 @@ class PriceModel with ChangeNotifier { _checkedCurrency = CurrencySelectorHelper().getSelected(userPreferences.userCurrencyCode); - _checkedPaidPrice = validateDouble(_paidPrice)!; - _checkedPriceWithoutDiscount = null; - if (promo) { - if (_priceWithoutDiscount.isNotEmpty) { - _checkedPriceWithoutDiscount = validateDouble(_priceWithoutDiscount); - if (_checkedPriceWithoutDiscount == null) { - return appLocalizations.prices_amount_price_incorrect; - } - } + final String? checkParameters = priceAmountModel.checkParameters(context); + if (checkParameters != null) { + return checkParameters; } if (location == null) { @@ -118,16 +92,18 @@ class PriceModel with ChangeNotifier { /// Adds the related background task. Future addTask(final BuildContext context) async => BackgroundTaskAddPrice.addTask( + context: context, + // per receipt cropObject: cropParameters!, locationOSMId: location!.osmId, locationOSMType: location!.osmType, date: date, proofType: proofType, currency: _checkedCurrency, - barcode: barcode, - priceIsDiscounted: promo, - price: _checkedPaidPrice, - priceWithoutDiscount: _checkedPriceWithoutDiscount, - context: context, + // per item + barcode: priceAmountModel.product.barcode, + priceIsDiscounted: priceAmountModel.promo, + price: priceAmountModel.checkedPaidPrice, + priceWithoutDiscount: priceAmountModel.checkedPriceWithoutDiscount, ); } diff --git a/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart b/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart new file mode 100644 index 00000000000..31cb5f3a0ff --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_product_image.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; + +/// Displays a meta product with an action button, as a ListTile. +class PriceProductListTile extends StatelessWidget { + const PriceProductListTile({ + required this.product, + this.trailingIconData, + this.onPressed, + }); + + final PriceMetaProduct product; + final IconData? trailingIconData; + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final Size screenSize = MediaQuery.sizeOf(context); + final double size = screenSize.width * 0.20; + final Widget child = Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: size, + child: product.product != null + ? SmoothMainProductImage( + product: product.product!, + width: size, + height: size, + ) + : SmoothImage( + width: size, + height: size, + imageProvider: product.imageUrl == null + ? null + : NetworkImage(product.imageUrl!), + ), + ), + const SizedBox(width: SMALL_SPACE), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(product.getName(appLocalizations)), + Text(product.barcode), + ], + ), + ), + if (trailingIconData != null) Icon(trailingIconData), + ], + ); + if (onPressed == null) { + return child; + } + return InkWell( + onTap: onPressed, + child: child, + ); + } +} diff --git a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart new file mode 100644 index 00000000000..3d238807434 --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart @@ -0,0 +1,178 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/fetched_product.dart'; +import 'package:smooth_app/database/dao_product.dart'; +import 'package:smooth_app/database/local_database.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/loading_dialog.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; +import 'package:smooth_app/pages/prices/price_product_list_tile.dart'; +import 'package:smooth_app/pages/product/common/product_refresher.dart'; +import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Product Search Page, for Prices. +class PriceProductSearchPage extends StatefulWidget { + const PriceProductSearchPage( + this.product, + ); + + final PriceMetaProduct product; + // TODO(monsieurtanuki): as a parameter, add a list of barcodes already there: we're not supposed to select twice the same product + + @override + State createState() => _PriceProductSearchPageState(); +} + +class _PriceProductSearchPageState extends State { + final TextEditingController _controller = TextEditingController(); + + late PriceMetaProduct? _product = widget.product; + + // TODO(monsieurtanuki): TextInputAction + focus + static const TextInputType _textInputType = TextInputType.number; + + @override + void initState() { + super.initState(); + _controller.text = _product?.barcode ?? ''; + } + + static const String _barcodeHint = '7300400481588'; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final LocalDatabase localDatabase = context.read(); + // TODO(monsieurtanuki): add WillPopScope2 + return SmoothScaffold( + appBar: SmoothAppBar( + centerTitle: false, + leading: const SmoothBackButton(), + title: Text(appLocalizations.prices_barcode_search_title), + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(LARGE_SPACE), + child: Column( + children: [ + // TODO(monsieurtanuki): add a "clear" button + // TODO(monsieurtanuki): add an automatic "validate barcode" feature (cf. https://en.wikipedia.org/wiki/International_Article_Number#Check_digit) + SmoothTextFormField( + type: TextFieldTypes.PLAIN_TEXT, + controller: _controller, + hintText: _barcodeHint, + textInputType: _textInputType, + onChanged: (_) async { + final String barcode = _controller.text; + final String cleanBarcode = _getCleanBarcode(barcode); + if (barcode != cleanBarcode) { + setState(() => _controller.text = cleanBarcode); + return; + } + + if (_product != null) { + setState( + () => _product = null, + ); + } + + final Product? product = await _localSearch( + barcode, + localDatabase, + ); + if (product != null) { + setState( + () => _product = PriceMetaProduct.product(product), + ); + return; + } + }, + onFieldSubmitted: (_) async { + final String barcode = _controller.text; + if (barcode.isEmpty) { + return; + } + + final Product? product = await _serverSearch( + barcode, + localDatabase, + context, + ); + if (product != null) { + setState(() => _product = PriceMetaProduct.product(product)); + } + }, + prefixIcon: const Icon(CupertinoIcons.barcode), + textInputAction: TextInputAction.search, + ), + if (_product != null) + Padding( + padding: const EdgeInsets.symmetric(vertical: LARGE_SPACE), + child: PriceProductListTile( + product: _product!, + trailingIconData: Icons.check_circle, + onPressed: () => Navigator.of(context).pop(_product), + ), + ), + ], + ), + ), + ); + } + + Future _localSearch( + final String barcode, + final LocalDatabase localDatabase, + ) async => + DaoProduct(localDatabase).get(barcode); + + Future _serverSearch( + final String barcode, + final LocalDatabase localDatabase, + final BuildContext context, + ) async { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final FetchedProduct? fetchAndRefreshed = + await LoadingDialog.run( + future: ProductRefresher().silentFetchAndRefresh( + localDatabase: localDatabase, + barcode: barcode, + ), + context: context, + title: appLocalizations.prices_barcode_search_running(barcode), + ); + if (fetchAndRefreshed == null) { + // the user probably cancelled + return null; + } + if (fetchAndRefreshed.product == null) { + if (context.mounted) { + await LoadingDialog.error( + context: context, + title: fetchAndRefreshed.getErrorTitle(appLocalizations), + ); + } + } + return fetchAndRefreshed.product; + } + + // Probably there's a regexp for that, but at least it's readable code. + String _getCleanBarcode(final String input) { + const int ascii0 = 48; + const int ascii9 = 48 + 10 - 1; + + final StringBuffer buffer = StringBuffer(); + for (int i = 0; i < input.length; i++) { + final int charCode = input.codeUnitAt(i); + if (charCode >= ascii0 && charCode <= ascii9) { + buffer.writeCharCode(charCode); + } + } + return buffer.toString(); + } +} diff --git a/packages/smooth_app/lib/pages/prices/price_product_widget.dart b/packages/smooth_app/lib/pages/prices/price_product_widget.dart index e8631362a86..e27b604313c 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_widget.dart @@ -18,10 +18,10 @@ class PriceProductWidget extends StatelessWidget { final PriceProduct priceProduct; final GetPricesModel model; - static const double _imageSize = 75; - @override Widget build(BuildContext context) { + final Size screenSize = MediaQuery.sizeOf(context); + final double size = screenSize.width * 0.20; final AppLocalizations appLocalizations = AppLocalizations.of(context); final String name = priceProduct.name ?? priceProduct.code; final bool unknown = priceProduct.name == null; @@ -31,75 +31,62 @@ class PriceProductWidget extends StatelessWidget { final String? quantity = priceProduct.quantity == null ? null : '${priceProduct.quantity} ${priceProduct.quantityUnit ?? 'g'}'; - return LayoutBuilder( - builder: ( - final BuildContext context, - final BoxConstraints constraints, - ) => - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: _imageSize, - child: imageURL == null - ? const Icon( - Icons.question_mark, - size: _imageSize / 2, - ) - : SmoothImage( - width: _imageSize, - height: _imageSize, - imageProvider: NetworkImage(imageURL), - ), + return Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: size, + child: SmoothImage( + width: size, + height: size, + imageProvider: imageURL == null ? null : NetworkImage(imageURL), ), - const SizedBox(width: SMALL_SPACE), - SizedBox( - width: constraints.maxWidth - _imageSize - SMALL_SPACE, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AutoSizeText( - name, - maxLines: 2, - style: Theme.of(context).textTheme.titleMedium, - ), - Wrap( - spacing: VERY_SMALL_SPACE, - crossAxisAlignment: WrapCrossAlignment.center, - runSpacing: 0, - children: [ - PriceCountWidget( - priceCount, - barcode: priceProduct.code, - name: name, - enableCountButton: model.enableCountButton, - ), - if (brands != null) - for (final String brand in brands) - PriceButton( - title: brand, - onPressed: () {}, - ), - if (quantity != null) Text(quantity), - if (unknown) + ), + const SizedBox(width: SMALL_SPACE), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AutoSizeText( + name, + maxLines: 2, + style: Theme.of(context).textTheme.titleMedium, + ), + Wrap( + spacing: VERY_SMALL_SPACE, + crossAxisAlignment: WrapCrossAlignment.center, + runSpacing: 0, + children: [ + PriceCountWidget( + priceCount, + priceProduct: priceProduct, + enableCountButton: model.enableCountButton, + ), + if (brands != null) + for (final String brand in brands) PriceButton( - title: appLocalizations.prices_unknown_product, - iconData: Icons.warning, - onPressed: null, - buttonStyle: ElevatedButton.styleFrom( - disabledForegroundColor: Colors.red, - disabledBackgroundColor: Colors.red[100], - ), + title: brand, + onPressed: () {}, + ), + if (quantity != null) Text(quantity), + if (unknown) + PriceButton( + title: appLocalizations.prices_unknown_product, + iconData: Icons.warning, + onPressed: null, + buttonStyle: ElevatedButton.styleFrom( + disabledForegroundColor: Colors.red, + disabledBackgroundColor: Colors.red[100], ), - ], - ), - ], - ), + ), + ], + ), + ], ), - ], - ), + ), + ], ); } } diff --git a/packages/smooth_app/lib/pages/prices/prices_card.dart b/packages/smooth_app/lib/pages/prices/prices_card.dart index cc362a0b26a..9ef74d1fd32 100644 --- a/packages/smooth_app/lib/pages/prices/prices_card.dart +++ b/packages/smooth_app/lib/pages/prices/prices_card.dart @@ -6,6 +6,7 @@ import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dar import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; import 'package:smooth_app/pages/prices/product_price_add_page.dart'; @@ -40,7 +41,7 @@ class PricesCard extends StatelessWidget { MaterialPageRoute( builder: (BuildContext context) => PricesPage( GetPricesModel.product( - product: product, + product: PriceMetaProduct.product(product), context: context, ), ), @@ -55,7 +56,7 @@ class PricesCard extends StatelessWidget { icon: Icons.add, onPressed: () async => ProductPriceAddPage.showProductPage( context: context, - product: product, + product: PriceMetaProduct.product(product), ), ), ), diff --git a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart index bbee46f7398..7fdf98d68f9 100644 --- a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart +++ b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart @@ -8,12 +8,12 @@ import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; -import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/locations/osm_location.dart'; import 'package:smooth_app/pages/prices/price_amount_card.dart'; import 'package:smooth_app/pages/prices/price_currency_card.dart'; import 'package:smooth_app/pages/prices/price_date_card.dart'; import 'package:smooth_app/pages/prices/price_location_card.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/price_model.dart'; import 'package:smooth_app/pages/prices/price_proof_card.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; @@ -23,43 +23,16 @@ import 'package:smooth_app/widgets/smooth_scaffold.dart'; /// Single page that displays all the elements of price adding. class ProductPriceAddPage extends StatefulWidget { const ProductPriceAddPage({ - required this.barcode, - required this.title, + required this.product, required this.latestOsmLocations, }); - final String barcode; - final String title; + final PriceMetaProduct product; final List latestOsmLocations; - static Future showBarcodePage({ - required final BuildContext context, - required final String barcode, - required final String title, - }) async => - _showPage( - context: context, - barcode: barcode, - title: title, - ); - static Future showProductPage({ required final BuildContext context, - required final Product product, - }) async => - _showPage( - context: context, - barcode: product.barcode!, - title: getProductNameAndBrands( - product, - AppLocalizations.of(context), - ), - ); - - static Future _showPage({ - required final BuildContext context, - required final String barcode, - required final String title, + required final PriceMetaProduct product, }) async { if (!await ProductRefresher().checkIfLoggedIn( context, @@ -79,8 +52,7 @@ class ProductPriceAddPage extends StatefulWidget { await Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => ProductPriceAddPage( - barcode: barcode, - title: title, + product: product, latestOsmLocations: osmLocations, ), ), @@ -95,7 +67,7 @@ class _ProductPriceAddPageState extends State { late final PriceModel _model = PriceModel( proofType: ProofType.priceTag, locations: widget.latestOsmLocations, - barcode: widget.barcode, + product: widget.product, ); final GlobalKey _formKey = GlobalKey(); @@ -113,10 +85,8 @@ class _ProductPriceAddPageState extends State { centerTitle: false, leading: const SmoothBackButton(), title: Text( - widget.title, - maxLines: 1, + appLocalizations.prices_add_a_price, ), - subTitle: Text(widget.barcode), actions: [ IconButton( icon: const Icon(Icons.info), @@ -124,48 +94,27 @@ class _ProductPriceAddPageState extends State { ), ], ), - body: const SingleChildScrollView( - padding: EdgeInsets.all(LARGE_SPACE), + body: SingleChildScrollView( + padding: const EdgeInsets.all(LARGE_SPACE), child: Column( children: [ - PriceProofCard(), - SizedBox(height: LARGE_SPACE), - PriceDateCard(), - SizedBox(height: LARGE_SPACE), - PriceLocationCard(), - SizedBox(height: LARGE_SPACE), - PriceCurrencyCard(), - SizedBox(height: LARGE_SPACE), - PriceAmountCard(), + const PriceProofCard(), + const SizedBox(height: LARGE_SPACE), + const PriceDateCard(), + const SizedBox(height: LARGE_SPACE), + const PriceLocationCard(), + const SizedBox(height: LARGE_SPACE), + const PriceCurrencyCard(), + const SizedBox(height: LARGE_SPACE), + PriceAmountCard(_model.priceAmountModel), // so that the last items don't get hidden by the FAB - SizedBox(height: MINIMUM_TOUCH_SIZE * 2), + const SizedBox(height: MINIMUM_TOUCH_SIZE * 2), ], ), ), floatingActionButton: FloatingActionButton.extended( onPressed: () async { - if (!_formKey.currentState!.validate()) { - return; - } - - String? error; - try { - error = await _model.checkParameters(context); - } catch (e) { - error = e.toString(); - } - if (error != null) { - if (!context.mounted) { - return; - } - await showDialog( - context: context, - builder: (BuildContext context) => - SmoothSimpleErrorAlertDialog( - title: appLocalizations.prices_add_validation_error, - message: error!, - ), - ); + if (!await _check(context)) { return; } if (!context.mounted) { @@ -222,4 +171,32 @@ class _ProductPriceAddPageState extends State { ), ); } + + /// Returns true if the basic checks passed. + Future _check(final BuildContext context) async { + if (!_formKey.currentState!.validate()) { + return false; + } + + String? error; + try { + error = _model.checkParameters(context); + } catch (e) { + error = e.toString(); + } + if (error != null) { + if (!context.mounted) { + return false; + } + await showDialog( + context: context, + builder: (BuildContext context) => SmoothSimpleErrorAlertDialog( + title: AppLocalizations.of(context).prices_add_validation_error, + message: error!, + ), + ); + return false; + } + return true; + } } diff --git a/packages/smooth_app/lib/pages/product/edit_product_page.dart b/packages/smooth_app/lib/pages/product/edit_product_page.dart index ebf61e83145..fe41b9d5615 100644 --- a/packages/smooth_app/lib/pages/product/edit_product_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_product_page.dart @@ -13,6 +13,7 @@ import 'package:smooth_app/generic_lib/widgets/smooth_list_tile_card.dart'; import 'package:smooth_app/generic_lib/widgets/svg_icon.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/product_price_add_page.dart'; import 'package:smooth_app/pages/product/add_other_details_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; @@ -259,7 +260,7 @@ class _EditProductPageState extends State with UpToDateMixin { leading: const Icon(Icons.add), onTap: () async => ProductPriceAddPage.showProductPage( context: context, - product: upToDateProduct, + product: PriceMetaProduct.product(upToDateProduct), ), ), ], From f4463054ca2ae986056b10462d03cd16ad0d1f40 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 14 Jun 2024 18:40:30 +0200 Subject: [PATCH 05/85] Dev mode with sections + reordered (#5372) --- packages/smooth_app/lib/l10n/app_en.arb | 5 + .../user_preferences_dev_mode.dart | 215 ++++++++++-------- .../preferences/user_preferences_item.dart | 2 +- .../preferences/user_preferences_widgets.dart | 64 +++++- 4 files changed, 176 insertions(+), 110 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 62fe2061924..d5f2957ce10 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1736,6 +1736,11 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart index 2755008e482..ca57ab676a2 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart @@ -98,74 +98,35 @@ class UserPreferencesDevMode extends AbstractUserPreferences { value: userPreferences.devMode == 1, ), UserPreferencesItemTile( - title: appLocalizations.dev_preferences_reset_onboarding_title, - subtitle: appLocalizations.dev_preferences_reset_onboarding_subtitle, - onTap: () async { - await userPreferences.resetOnboarding(); - _showSuccessMessage(); - }, + title: 'Debugging information', + onTap: () async => Navigator.of(context).push(MaterialPageRoute( + builder: (BuildContext context) => + const UserPreferencesDebugInfo())), + ), + UserPreferencesItemSection( + label: appLocalizations.dev_mode_section_data, ), UserPreferencesItemTile( - title: appLocalizations.dev_preferences_environment_switch_title, - trailing: DropdownButton( - value: userPreferences.getFlag(userPreferencesFlagProd) ?? true, - elevation: 16, - onChanged: (bool? newValue) async { - await userPreferences.setFlag(userPreferencesFlagProd, newValue); - ProductQuery.setQueryType(userPreferences); - }, - items: const >[ - DropdownMenuItem( - value: true, - child: Text('PROD'), - ), - DropdownMenuItem( - value: false, - child: Text('TEST'), - ), - ], + title: appLocalizations.background_task_title, + subtitle: appLocalizations.background_task_subtitle, + trailing: const BackgroundTaskBadge( + child: Icon(Icons.edit_notifications_outlined), + ), + onTap: () async => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => const OfflineTaskPage(), + ), ), ), UserPreferencesItemTile( - title: appLocalizations.dev_preferences_test_environment_title, - subtitle: appLocalizations.dev_preferences_test_environment_subtitle( - ProductQuery.getTestUriProductHelper(userPreferences) - .getPostUri(path: '') - .toString(), + title: appLocalizations.offline_data, + onTap: () => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => const OfflineDataPage(), + ), ), - onTap: () async => _changeTestEnvDomain(), - ), - UserPreferencesItemSwitch( - title: appLocalizations.dev_preferences_edit_ingredients_title, - value: userPreferences.getFlag(userPreferencesFlagEditIngredients) ?? - false, - onChanged: (bool value) async { - await userPreferences.setFlag( - userPreferencesFlagEditIngredients, value); - _showSuccessMessage(); - }, - ), - UserPreferencesItemSwitch( - title: 'Accessibility: remove colors', - value: userPreferences - .getFlag(userPreferencesFlagAccessibilityNoColor) ?? - false, - onChanged: (bool value) async { - await userPreferences.setFlag( - userPreferencesFlagAccessibilityNoColor, value); - _showSuccessMessage(); - }, - ), - UserPreferencesItemSwitch( - title: 'Accessibility: show emoji', - value: - userPreferences.getFlag(userPreferencesFlagAccessibilityEmoji) ?? - false, - onChanged: (bool value) async { - await userPreferences.setFlag( - userPreferencesFlagAccessibilityEmoji, value); - _showSuccessMessage(); - }, ), UserPreferencesItemTile( title: appLocalizations.dev_preferences_export_history_title, @@ -235,26 +196,23 @@ class UserPreferencesDevMode extends AbstractUserPreferences { }, ), UserPreferencesItemTile( - title: appLocalizations.offline_data, - onTap: () => Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => const OfflineDataPage(), - ), - ), + title: 'Refresh all products from server (cf. Nutriscore v2)', + trailing: const Icon(Icons.refresh), + onTap: () async { + final LocalDatabase localDatabase = context.read(); + final DaoProduct daoProduct = DaoProduct(localDatabase); + await daoProduct.clearAllLanguages(); + await BackgroundTaskLanguageRefresh.addTask(localDatabase); + _showSuccessMessage(); + }, ), UserPreferencesItemTile( - title: appLocalizations.background_task_title, - subtitle: appLocalizations.background_task_subtitle, - trailing: const BackgroundTaskBadge( - child: Icon(Icons.edit_notifications_outlined), - ), - onTap: () async => Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => const OfflineTaskPage(), - ), - ), + // Do not translate + title: 'Reset app language', + onTap: () async { + userPreferences.setAppLanguageCode(null); + ProductQuery.setLanguage(context, userPreferences); + }, ), UserPreferencesItemTile( title: 'Add cards to scanner', @@ -273,6 +231,52 @@ class UserPreferencesDevMode extends AbstractUserPreferences { } }, ), + UserPreferencesItemSection( + label: appLocalizations.dev_mode_section_server, + ), + UserPreferencesItemTile( + title: appLocalizations.dev_preferences_environment_switch_title, + trailing: DropdownButton( + value: userPreferences.getFlag(userPreferencesFlagProd) ?? true, + elevation: 16, + onChanged: (bool? newValue) async { + await userPreferences.setFlag(userPreferencesFlagProd, newValue); + ProductQuery.setQueryType(userPreferences); + }, + items: const >[ + DropdownMenuItem( + value: true, + child: Text('PROD'), + ), + DropdownMenuItem( + value: false, + child: Text('TEST'), + ), + ], + ), + ), + UserPreferencesItemTile( + title: appLocalizations.dev_preferences_test_environment_title, + subtitle: appLocalizations.dev_preferences_test_environment_subtitle( + ProductQuery.getTestUriProductHelper(userPreferences) + .getPostUri(path: '') + .toString(), + ), + onTap: () async => _changeTestEnvDomain(), + ), + UserPreferencesItemSection( + label: appLocalizations.dev_mode_section_product_page, + ), + UserPreferencesItemSwitch( + title: appLocalizations.dev_preferences_edit_ingredients_title, + value: userPreferences.getFlag(userPreferencesFlagEditIngredients) ?? + false, + onChanged: (bool value) async { + await userPreferences.setFlag( + userPreferencesFlagEditIngredients, value); + _showSuccessMessage(); + }, + ), UserPreferencesItemSwitch( title: appLocalizations.dev_mode_hide_ecoscore_title, value: userPreferences @@ -288,41 +292,41 @@ class UserPreferencesDevMode extends AbstractUserPreferences { await userPreferences.setExcludedAttributeIds(list); }, ), + UserPreferencesItemSection( + label: appLocalizations.dev_mode_section_ui, + ), UserPreferencesItemTile( - // Do not translate - title: 'Reset app language', + title: appLocalizations.dev_preferences_reset_onboarding_title, + subtitle: appLocalizations.dev_preferences_reset_onboarding_subtitle, onTap: () async { - userPreferences.setAppLanguageCode(null); - ProductQuery.setLanguage(context, userPreferences); + await userPreferences.resetOnboarding(); + _showSuccessMessage(); }, ), - UserPreferencesItemTile( - title: 'Refresh all products from server (cf. Nutriscore v2)', - trailing: const Icon(Icons.refresh), - onTap: () async { - final LocalDatabase localDatabase = context.read(); - final DaoProduct daoProduct = DaoProduct(localDatabase); - await daoProduct.clearAllLanguages(); - await BackgroundTaskLanguageRefresh.addTask(localDatabase); + UserPreferencesItemSwitch( + title: 'Accessibility: remove colors', + value: userPreferences + .getFlag(userPreferencesFlagAccessibilityNoColor) ?? + false, + onChanged: (bool value) async { + await userPreferences.setFlag( + userPreferencesFlagAccessibilityNoColor, value); _showSuccessMessage(); }, ), UserPreferencesItemSwitch( - title: 'Side by side comparison for 2 or 3 products', + title: 'Accessibility: show emoji', value: - userPreferences.getFlag(userPreferencesFlagBoostedComparison) ?? + userPreferences.getFlag(userPreferencesFlagAccessibilityEmoji) ?? false, onChanged: (bool value) async { await userPreferences.setFlag( - userPreferencesFlagBoostedComparison, value); + userPreferencesFlagAccessibilityEmoji, value); _showSuccessMessage(); }, ), - UserPreferencesItemTile( - title: 'Debugging information', - onTap: () async => Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => - const UserPreferencesDebugInfo())), + UserPreferencesItemSection( + label: appLocalizations.dev_mode_section_experimental_features, ), UserPreferencesItemSwitch( title: 'User ordered knowledge panels', @@ -391,6 +395,17 @@ class UserPreferencesDevMode extends AbstractUserPreferences { ), ), ), + UserPreferencesItemSwitch( + title: 'Side by side comparison for 2 or 3 products', + value: + userPreferences.getFlag(userPreferencesFlagBoostedComparison) ?? + false, + onChanged: (bool value) async { + await userPreferences.setFlag( + userPreferencesFlagBoostedComparison, value); + _showSuccessMessage(); + }, + ), ]; ScaffoldFeatureController diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_item.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_item.dart index f7f3f84497c..2e4b90c512d 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_item.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_item.dart @@ -17,5 +17,5 @@ class UserPreferencesItemSimple implements UserPreferencesItem { final Iterable labels; @override - final Widget Function(BuildContext) builder; + final WidgetBuilder builder; } diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart index 76390f6fdb1..44be303dd28 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:smooth_app/generic_lib/bottom_sheets/smooth_bottom_sheet.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/pages/preferences/user_preferences_item.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; /// A dashed line class UserPreferencesListItemDivider extends StatelessWidget { @@ -123,7 +124,7 @@ class UserPreferencesItemSwitch implements UserPreferencesItem { ]; @override - Widget Function(BuildContext) get builder => + WidgetBuilder get builder => (final BuildContext context) => UserPreferencesSwitchWidget( title: title, subtitle: subtitle, @@ -154,14 +155,59 @@ class UserPreferencesItemTile implements UserPreferencesItem { ]; @override - Widget Function(BuildContext) get builder => - (final BuildContext context) => ListTile( - title: Text(title), - subtitle: subtitle == null ? null : Text(subtitle!), - onTap: onTap, - leading: leading, - trailing: trailing, - ); + WidgetBuilder get builder => (final BuildContext context) => ListTile( + title: Text(title), + subtitle: subtitle == null ? null : Text(subtitle!), + onTap: onTap, + leading: leading, + trailing: trailing, + ); +} + +class UserPreferencesItemSection implements UserPreferencesItem { + const UserPreferencesItemSection({ + required this.label, + this.icon, + }) : assert(label.length > 0); + + final String label; + final Widget? icon; + + @override + WidgetBuilder get builder => (BuildContext context) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + + return Container( + color: colors.primaryDark, + padding: const EdgeInsets.symmetric( + horizontal: LARGE_SPACE, + vertical: SMALL_SPACE, + ), + child: Row( + children: [ + Expanded( + child: Text( + label, + style: TextStyle( + color: colors.primaryLight, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + if (icon != null) + IconTheme( + data: IconThemeData(color: colors.primaryLight), + child: icon!, + ), + ], + ), + ); + }; + + @override + Iterable get labels => [label]; } /// A preference allowing to choose between a list of items. From 5786f53d411499cf0516058ffaa8abaecffdb8bf Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 14 Jun 2024 18:41:04 +0200 Subject: [PATCH 06/85] Preview badge (#5368) --- .../smooth_app/assets/fonts/SmoothIcons.ttf | Bin 17028 -> 17880 bytes .../smooth_app/assets/fonts/icons/config.json | 42 ++++++++++++++++ .../assets/fonts/icons/icons.sketch | Bin 84381 -> 122259 bytes .../smooth_app/assets/fonts/icons/lab.svg | 7 +++ .../assets/fonts/icons/magic_wand.svg | 7 +++ .../assets/fonts/icons/sparkles.svg | 7 +++ packages/smooth_app/lib/l10n/app_en.arb | 4 ++ .../lib/pages/prices/prices_card.dart | 45 ++++++++++++++++-- .../smooth_app/lib/resources/app_icons.dart | 27 +++++++++++ .../lib/resources/app_icons_font.dart | 6 +++ 10 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 packages/smooth_app/assets/fonts/icons/lab.svg create mode 100644 packages/smooth_app/assets/fonts/icons/magic_wand.svg create mode 100644 packages/smooth_app/assets/fonts/icons/sparkles.svg diff --git a/packages/smooth_app/assets/fonts/SmoothIcons.ttf b/packages/smooth_app/assets/fonts/SmoothIcons.ttf index 24e388ab3a77ed49c2268d2b719d9c712d59715b..7765d978af5fc14800c4f4edef6a2de5dae063d8 100644 GIT binary patch delta 2133 zcmZXVe@t6d6vxkbukW?5uN3<0J)lr1w1qKNpe?O#&@yDolKtUWG6$NluCT!dZ5?DX zvsfiF!MGT-(Lc=oP_r$@=(2>xKNkL){^gQI|50P6nTsYbi!o-I#w^%+Zto*m^up(z zbM8I&-0!>Z-PiN4YW`G?!K`cHLQDvF0Gwt>KUsj+#PasXe%N9A>#DgS}J<)eb7+#)EfLOCRS zk#W|t0Bs=Fyk4^G{+(cfJ2c-54b)>XbfeV>8#|1+vClYUOd6M~RR9CZF){2x${K}n z`a1we;0(MB=gMcqv(gX@Lwe(Pu?`j5l3GibEmBuWq^Sfg0fq@k2N4^PY z*7FwY&Qqm$nM}kJK0?v2$GF* zpo4552RcjS^m8CYc7OwHAvy~Th>(qQfGwKj09!Q00k-H99OxnYBnNhq-OYhsvU@nd zgbfiTx&Tu)%mJn>%>gDX!vQ92gab_2UJfu}qZ~+(eToBvWXCwb1n=Vj6MT>ZB)DWu zP(T1ve24=~@evL%#giOhiZ5~KeFoz)2S{+Ot;1~`$BJ-7xFXyW9pW+ZV{yxpx7?PJ z(hG7z{>^$)X;h9Y?ss;jcs}vU z-n`H4o6~x=OWN1kBR!&D(7$TzZ@k{P)il<$*0j|;-u$KC;ve^~Z;aXA6-x8skKzPv zVhWyzb9C%G>ai;#x1rUES{tU4G0j_#K0ScR4C-1M`!JQp2wjsAmMNm_)nX~sJLFdE z>~NwtfP2vA)pU*WhA|#XB@mNJfM;j}p(h zn=LIvU0@YzNGB+g_(4yDFKl-!irXHx z+dLkdJ*=scq-tU9AscZ?sw%l?%;j_0F|1Jw3r*rg!&FPDR;jkYDyy}M<_ebcWdn zt9sJ%9PPGF$1cj=6AW(Lw`atX#D+wJhJ19ggLEM1Ek$44g)-Zvcrccx4eUZ!d{Bz} zI<0YR!(axngKd5?5wUJNsHG~m8UyiwXs1hKBqDu6lmxRRuU4C}9k3bON#YN8 z#|70|XC1#Q+nkU2Te~kNP<5!7C|#6oHhDW@0jBdIk&T6lY-l^k%QhKD{#(c_ieln_ zbV0b`X3FnpR{AiF85{v?Zf-tzYBsNCXJ)3C3)2hp zOUt&U+2!T={D~#|V)n#*Zu+Hcex}?%a=;=kWRI24jl>k&QZak_)WYo2#?_H;k$!mp E1+SH?eE-;gULkL8Z%5 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

o_otrUwV55%Qp2v>yZ6t6`-Psy&Bo+HTXT8 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

2)WTJJ5I(O5Ik$SVGDpp0K+?Kg- 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 literal 84381 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 diff --git a/packages/smooth_app/assets/fonts/icons/lab.svg b/packages/smooth_app/assets/fonts/icons/lab.svg new file mode 100644 index 00000000000..7f5e0d65912 --- /dev/null +++ b/packages/smooth_app/assets/fonts/icons/lab.svg @@ -0,0 +1,7 @@ + + + Laboratoy + + + + \ No newline at end of file diff --git a/packages/smooth_app/assets/fonts/icons/magic_wand.svg b/packages/smooth_app/assets/fonts/icons/magic_wand.svg new file mode 100644 index 00000000000..c89cd3fb94d --- /dev/null +++ b/packages/smooth_app/assets/fonts/icons/magic_wand.svg @@ -0,0 +1,7 @@ + + + Magic Wand + + + + \ No newline at end of file diff --git a/packages/smooth_app/assets/fonts/icons/sparkles.svg b/packages/smooth_app/assets/fonts/icons/sparkles.svg new file mode 100644 index 00000000000..6725e7d5cea --- /dev/null +++ b/packages/smooth_app/assets/fonts/icons/sparkles.svg @@ -0,0 +1,7 @@ + + + Sparkles + + + + \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index d5f2957ce10..573d9f16644 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -2755,5 +2755,9 @@ "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } diff --git a/packages/smooth_app/lib/pages/prices/prices_card.dart b/packages/smooth_app/lib/pages/prices/prices_card.dart index 9ef74d1fd32..3a5f9acdbe6 100644 --- a/packages/smooth_app/lib/pages/prices/prices_card.dart +++ b/packages/smooth_app/lib/pages/prices/prices_card.dart @@ -9,6 +9,8 @@ import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; import 'package:smooth_app/pages/prices/product_price_add_page.dart'; +import 'package:smooth_app/resources/app_icons.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; /// Card that displays buttons related to prices. class PricesCard extends StatelessWidget { @@ -19,6 +21,9 @@ class PricesCard extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); + final SmoothColorsThemeExtension? themeExtension = + Theme.of(context).extension(); + return buildProductSmoothCard( body: Container( width: double.infinity, @@ -27,9 +32,43 @@ class PricesCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - AppLocalizations.of(context).prices_generic_title, - style: Theme.of(context).textTheme.displaySmall, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context).prices_generic_title, + style: Theme.of(context).textTheme.displaySmall, + ), + const SizedBox(width: SMALL_SPACE), + Container( + decoration: BoxDecoration( + color: themeExtension!.secondaryNormal, + borderRadius: CIRCULAR_BORDER_RADIUS, + ), + margin: const EdgeInsets.only(top: 0.5), + padding: const EdgeInsets.symmetric( + horizontal: MEDIUM_SPACE, + vertical: VERY_SMALL_SPACE, + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Preview', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(width: SMALL_SPACE), + Lab( + color: Colors.white, + size: 13.0, + ), + ], + ), + ), + ], ), const SizedBox(height: SMALL_SPACE), Padding( diff --git a/packages/smooth_app/lib/resources/app_icons.dart b/packages/smooth_app/lib/resources/app_icons.dart index 7b6bcb70606..2d6dc46fdaa 100644 --- a/packages/smooth_app/lib/resources/app_icons.dart +++ b/packages/smooth_app/lib/resources/app_icons.dart @@ -373,6 +373,15 @@ class Ingredients extends AppIcon { }) : super._(_IconsFont.ingredients); } +class Lab extends AppIcon { + const Lab({ + super.color, + super.size, + super.shadow, + super.key, + }) : super._(_IconsFont.lab); +} + class Labels extends AppIcon { const Labels({ super.color, @@ -391,6 +400,15 @@ class Lifebuoy extends AppIcon { }) : super._(_IconsFont.lifebuoy); } +class MagicWand extends AppIcon { + const MagicWand({ + super.color, + super.size, + super.shadow, + super.key, + }) : super._(_IconsFont.magic_wand); +} + class Milk extends AppIcon { const Milk({ super.color, @@ -582,6 +600,15 @@ class Sound extends AppIcon { }) : super._(_IconsFont.sound_off); } +class Sparkles extends AppIcon { + const Sparkles({ + super.color, + super.size, + super.shadow, + super.key, + }) : super._(_IconsFont.sparkles); +} + class Stores extends AppIcon { const Stores({ super.color, diff --git a/packages/smooth_app/lib/resources/app_icons_font.dart b/packages/smooth_app/lib/resources/app_icons_font.dart index cd58f28eae4..1140bedf2ed 100644 --- a/packages/smooth_app/lib/resources/app_icons_font.dart +++ b/packages/smooth_app/lib/resources/app_icons_font.dart @@ -16,6 +16,8 @@ class _IconsFont { IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData settings = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData magic_wand = + IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData camera_outlined = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData camera_filled = @@ -28,6 +30,8 @@ class _IconsFont { IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData circled_arrow = IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData lab = + IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData compare = IconData(0xe80b, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData countries = @@ -40,6 +44,8 @@ class _IconsFont { IconData(0xe80f, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData expand = IconData(0xe810, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData sparkles = + IconData(0xe811, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData fruit = IconData(0xe812, fontFamily: _kFontFam, fontPackage: _kFontPkg); static const IconData info = From 9e3cea3ac388f5c1df0d30770a375ce74c7a18c7 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 14 Jun 2024 19:26:56 +0200 Subject: [PATCH 07/85] Hide Robotoff banner on the onboarding (#5369) --- .../lib/pages/onboarding/preferences_page.dart | 1 + .../smooth_app/lib/pages/product/new_product_page.dart | 1 - packages/smooth_app/lib/pages/product/summary_card.dart | 9 +++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/smooth_app/lib/pages/onboarding/preferences_page.dart b/packages/smooth_app/lib/pages/onboarding/preferences_page.dart index c65173a859d..6f7d4445b10 100644 --- a/packages/smooth_app/lib/pages/onboarding/preferences_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/preferences_page.dart @@ -109,6 +109,7 @@ class _HelperState extends State<_Helper> { isRemovable: false, isSettingVisible: false, isProductEditable: false, + showQuestionsBanner: false, ), ), ]; diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index 57f7897a739..d5e70156a3c 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -217,7 +217,6 @@ class _ProductPageState extends State upToDateProduct, _productPreferences, isFullVersion: true, - showUnansweredQuestions: true, ), ), ), diff --git a/packages/smooth_app/lib/pages/product/summary_card.dart b/packages/smooth_app/lib/pages/product/summary_card.dart index 2a430b6e974..6245291f22e 100644 --- a/packages/smooth_app/lib/pages/product/summary_card.dart +++ b/packages/smooth_app/lib/pages/product/summary_card.dart @@ -17,6 +17,7 @@ import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/helpers/ui_helpers.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_page.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels_builder.dart'; +import 'package:smooth_app/pages/hunger_games/question_card.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/pages/product/hideable_container.dart'; import 'package:smooth_app/pages/product/product_compatibility_header.dart'; @@ -41,7 +42,7 @@ class SummaryCard extends StatefulWidget { this._product, this._productPreferences, { this.isFullVersion = false, - this.showUnansweredQuestions = false, + this.showQuestionsBanner = false, this.isRemovable = true, this.isSettingVisible = true, this.isProductEditable = true, @@ -58,9 +59,8 @@ class SummaryCard extends StatefulWidget { /// Buttons should only be visible in full mode final bool isFullVersion; - /// If true, the summary card will try to load unanswered questions about this - /// product and give a prompt to answer those questions. - final bool showUnansweredQuestions; + /// If true, show the [QuestionCard] if there are questions for the product. + final bool showQuestionsBanner; /// If true, there will be a button to remove the product from the carousel. final bool isRemovable; @@ -347,6 +347,7 @@ class _SummaryCardState extends State with UpToDateMixin { ProductIncompleteCard(product: upToDateProduct), ..._getAttributes(scoreAttributes), if (widget.isFullVersion && + widget.showQuestionsBanner && _questionsLayout == ProductQuestionsLayout.button) ProductQuestionsWidget( upToDateProduct, From b3009557eca4aba1f184aac1abd56250e36c5067 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Fri, 14 Jun 2024 19:38:13 +0200 Subject: [PATCH 08/85] feat: 5204 - multi-product price addition (#5375) * feat: 5204 - multi-product price addition Impacted files: * `app_en.arb`: added 3 labels and removed one redundant one * `app_fr.arb`: added 3 labels and removed one redundant one * `background_task_add_price.dart`: now we manage multiple products, in `List`s * `price_amount_card.dart`: small UI/UX differences for a single product among several products; minor code simplification * `price_model.dart`: now we manage multiple products * `price_product_search_page.dart`: added "no initial product" case * `product_price_add_page.dart`: now we manage multiple products * Minor fix --- .../background/background_task_add_price.dart | 165 ++++++++++++------ packages/smooth_app/lib/l10n/app_en.arb | 4 +- packages/smooth_app/lib/l10n/app_fr.arb | 4 +- .../lib/pages/prices/price_amount_card.dart | 72 ++++---- .../lib/pages/prices/price_model.dart | 57 +++--- .../prices/price_product_search_page.dart | 6 +- .../pages/prices/product_price_add_page.dart | 46 ++++- 7 files changed, 235 insertions(+), 119 deletions(-) diff --git a/packages/smooth_app/lib/background/background_task_add_price.dart b/packages/smooth_app/lib/background/background_task_add_price.dart index 27ad4c24f5b..bff36bc9f2c 100644 --- a/packages/smooth_app/lib/background/background_task_add_price.dart +++ b/packages/smooth_app/lib/background/background_task_add_price.dart @@ -16,8 +16,6 @@ import 'package:smooth_app/pages/prices/eraser_model.dart'; import 'package:smooth_app/pages/prices/eraser_painter.dart'; // TODO(monsieurtanuki): use transient file, in order to have instant access to proof image? -// TODO(monsieurtanuki): add source -// TODO(monsieurtanuki): make it work for several products /// Background task about adding a product price. class BackgroundTaskAddPrice extends BackgroundTask { BackgroundTaskAddPrice._({ @@ -39,10 +37,10 @@ class BackgroundTaskAddPrice extends BackgroundTask { // lines required this.eraserCoordinates, // multi - required this.barcode, - required this.priceIsDiscounted, - required this.price, - required this.priceWithoutDiscount, + required this.barcodes, + required this.pricesAreDiscounted, + required this.prices, + required this.pricesWithoutDiscount, }); BackgroundTaskAddPrice.fromJson(Map json) @@ -60,10 +58,18 @@ class BackgroundTaskAddPrice extends BackgroundTask { LocationOSMType.fromOffTag(json[_jsonTagOSMType] as String)!, eraserCoordinates = _fromJsonListDouble(json[_jsonTagEraserCoordinates]), - barcode = json[_jsonTagBarcode] as String, - priceIsDiscounted = json[_jsonTagIsDiscounted] as bool, - price = json[_jsonTagPrice] as double, - priceWithoutDiscount = json[_jsonTagPriceWithoutDiscount] as double?, + barcodes = json.containsKey(_jsonTagBarcode) + ? [json[_jsonTagBarcode] as String] + : _fromJsonListString(json[_jsonTagBarcodes])!, + pricesAreDiscounted = json.containsKey(_jsonTagIsDiscounted) + ? [json[_jsonTagIsDiscounted] as bool] + : _fromJsonListBool(json[_jsonTagAreDiscounted])!, + prices = json.containsKey(_jsonTagPrice) + ? [json[_jsonTagPrice] as double] + : _fromJsonListDouble(json[_jsonTagPrices])!, + pricesWithoutDiscount = json.containsKey(_jsonTagPriceWithoutDiscount) + ? [json[_jsonTagPriceWithoutDiscount] as double?] + : _fromJsonListNullableDouble(json[_jsonTagPricesWithoutDiscount])!, super.fromJson(json); static List? _fromJsonListDouble(final List? input) { @@ -77,6 +83,41 @@ class BackgroundTaskAddPrice extends BackgroundTask { return result; } + static List? _fromJsonListNullableDouble( + final List? input, + ) { + if (input == null) { + return null; + } + final List result = []; + for (final dynamic item in input) { + result.add(item as double?); + } + return result; + } + + static List? _fromJsonListString(final List? input) { + if (input == null) { + return null; + } + final List result = []; + for (final dynamic item in input) { + result.add(item as String); + } + return result; + } + + static List? _fromJsonListBool(final List? input) { + if (input == null) { + return null; + } + final List result = []; + for (final dynamic item in input) { + result.add(item as bool); + } + return result; + } + static const String _jsonTagImagePath = 'imagePath'; static const String _jsonTagRotation = 'rotation'; static const String _jsonTagX1 = 'x1'; @@ -89,9 +130,17 @@ class BackgroundTaskAddPrice extends BackgroundTask { static const String _jsonTagCurrency = 'currency'; static const String _jsonTagOSMId = 'osmId'; static const String _jsonTagOSMType = 'osmType'; + static const String _jsonTagBarcodes = 'barcodes'; + static const String _jsonTagAreDiscounted = 'areDiscounted'; + static const String _jsonTagPrices = 'prices'; + static const String _jsonTagPricesWithoutDiscount = 'pricesWithoutDiscount'; + @Deprecated('Use [_jsonTagBarcodes] instead') static const String _jsonTagBarcode = 'barcode'; + @Deprecated('Use [_jsonTagAreDiscounted] instead') static const String _jsonTagIsDiscounted = 'isDiscounted'; + @Deprecated('Use [_jsonTagPrices] instead') static const String _jsonTagPrice = 'price'; + @Deprecated('Use [_jsonTagPricesWithoutDiscount] instead') static const String _jsonTagPriceWithoutDiscount = 'priceWithoutDiscount'; static const OperationType _operationType = OperationType.addPrice; @@ -108,10 +157,11 @@ class BackgroundTaskAddPrice extends BackgroundTask { final int locationOSMId; final LocationOSMType locationOSMType; final List? eraserCoordinates; - final String barcode; - final bool priceIsDiscounted; - final double price; - final double? priceWithoutDiscount; + // per line + final List barcodes; + final List pricesAreDiscounted; + final List prices; + final List pricesWithoutDiscount; @override Map toJson() { @@ -128,41 +178,41 @@ class BackgroundTaskAddPrice extends BackgroundTask { result[_jsonTagOSMId] = locationOSMId; result[_jsonTagOSMType] = locationOSMType.offTag; result[_jsonTagEraserCoordinates] = eraserCoordinates; - result[_jsonTagBarcode] = barcode; - result[_jsonTagIsDiscounted] = priceIsDiscounted; - result[_jsonTagPrice] = price; - result[_jsonTagPriceWithoutDiscount] = priceWithoutDiscount; + result[_jsonTagBarcodes] = barcodes; + result[_jsonTagAreDiscounted] = pricesAreDiscounted; + result[_jsonTagPrices] = prices; + result[_jsonTagPricesWithoutDiscount] = pricesWithoutDiscount; return result; } /// Adds the background task about uploading a product image. static Future addTask({ + required final BuildContext context, required final CropParameters cropObject, required final ProofType proofType, required final DateTime date, required final Currency currency, required final int locationOSMId, required final LocationOSMType locationOSMType, - required final String barcode, - required final bool priceIsDiscounted, - required final double price, - required final double? priceWithoutDiscount, - required final BuildContext context, + required final List barcodes, + required final List pricesAreDiscounted, + required final List prices, + required final List pricesWithoutDiscount, }) async { final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey(localDatabase); final BackgroundTask task = _getNewTask( + uniqueId: uniqueId, cropObject: cropObject, proofType: proofType, date: date, currency: currency, locationOSMId: locationOSMId, locationOSMType: locationOSMType, - barcode: barcode, - priceIsDiscounted: priceIsDiscounted, - price: price, - priceWithoutDiscount: priceWithoutDiscount, - uniqueId: uniqueId, + barcodes: barcodes, + pricesAreDiscounted: pricesAreDiscounted, + prices: prices, + pricesWithoutDiscount: pricesWithoutDiscount, ); if (!context.mounted) { return; @@ -180,17 +230,17 @@ class BackgroundTaskAddPrice extends BackgroundTask { /// Returns a new background task about changing a product. static BackgroundTaskAddPrice _getNewTask({ + required final String uniqueId, required final CropParameters cropObject, required final ProofType proofType, required final DateTime date, required final Currency currency, required final int locationOSMId, required final LocationOSMType locationOSMType, - required final String barcode, - required final bool priceIsDiscounted, - required final double price, - required final double? priceWithoutDiscount, - required final String uniqueId, + required final List barcodes, + required final List pricesAreDiscounted, + required final List prices, + required final List pricesWithoutDiscount, }) => BackgroundTaskAddPrice._( uniqueId: uniqueId, @@ -207,10 +257,10 @@ class BackgroundTaskAddPrice extends BackgroundTask { locationOSMId: locationOSMId, locationOSMType: locationOSMType, eraserCoordinates: cropObject.eraserCoordinates, - barcode: barcode, - priceIsDiscounted: priceIsDiscounted, - price: price, - priceWithoutDiscount: priceWithoutDiscount, + barcodes: barcodes, + pricesAreDiscounted: pricesAreDiscounted, + prices: prices, + pricesWithoutDiscount: pricesWithoutDiscount, stamp: _getStamp( date: date, locationOSMId: locationOSMId, @@ -250,16 +300,6 @@ class BackgroundTaskAddPrice extends BackgroundTask { @override Future execute(final LocalDatabase localDatabase) async { - final Price newPrice = Price() - ..date = date - ..currency = currency - ..locationOSMId = locationOSMId - ..locationOSMType = locationOSMType - ..priceIsDiscounted = priceIsDiscounted - ..price = price - ..priceWithoutDiscount = priceWithoutDiscount - ..productCode = barcode; - final List offsets = []; if (eraserCoordinates != null) { for (int i = 0; i < eraserCoordinates!.length; i += 2) { @@ -328,16 +368,29 @@ class BackgroundTaskAddPrice extends BackgroundTask { if (uploadProof.isError) { throw Exception('Could not upload proof: ${uploadProof.error}'); } - newPrice.proofId = uploadProof.value.id; - // create price - final MaybeError addedPrice = await OpenPricesAPIClient.createPrice( - price: newPrice, - bearerToken: bearerToken, - uriHelper: uriProductHelper, - ); - if (addedPrice.isError) { - throw Exception('Could not add price: ${addedPrice.error}'); + for (int i = 0; i < barcodes.length; i++) { + final Price newPrice = Price() + ..date = date + ..currency = currency + ..locationOSMId = locationOSMId + ..locationOSMType = locationOSMType + ..proofId = uploadProof.value.id + ..priceIsDiscounted = pricesAreDiscounted[i] + ..price = prices[i] + ..priceWithoutDiscount = pricesWithoutDiscount[i] + ..productCode = barcodes[i]; + + // create price + final MaybeError addedPrice = + await OpenPricesAPIClient.createPrice( + price: newPrice, + bearerToken: bearerToken, + uriHelper: uriProductHelper, + ); + if (addedPrice.isError) { + throw Exception('Could not add price: ${addedPrice.error}'); + } } // close session diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 573d9f16644..8c378f6d3d2 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1674,8 +1674,10 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", "prices_barcode_search_title": "Product search", "prices_barcode_search_running": "Looking for {barcode}", "@prices_barcode_search_running": { diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 8a0abe7c476..bde1e1bf2ba 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1674,8 +1674,10 @@ "prices_app_dev_mode_flag": "Raccourci vers l'application Prix sur la page produit", "prices_app_button": "Accéder à l'application Prix", "prices_generic_title": "Prix", + "prices_add_n_prices": "{count,plural, =1{Ajouter un prix} other{Ajouter {count} prix}}", + "prices_send_n_prices": "{count,plural, =1{Envoyer le prix} other{Envoyer {count} prix}}", + "prices_add_an_item": "Ajouter un article", "prices_add_a_price": "Ajouter un prix", - "prices_send_the_price": "Envoyer le prix", "prices_barcode_search_title": "Recherche de produit", "prices_barcode_search_running": "À la recherche de {barcode}", "@prices_barcode_search_running": { diff --git a/packages/smooth_app/lib/pages/prices/price_amount_card.dart b/packages/smooth_app/lib/pages/prices/price_amount_card.dart index 7ffc5ad9e7a..f5eb0b1d089 100644 --- a/packages/smooth_app/lib/pages/prices/price_amount_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_amount_card.dart @@ -5,13 +5,24 @@ import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/prices/price_amount_field.dart'; import 'package:smooth_app/pages/prices/price_amount_model.dart'; +import 'package:smooth_app/pages/prices/price_model.dart'; import 'package:smooth_app/pages/prices/price_product_list_tile.dart'; /// Card that displays the amounts (discounted or not) for price adding. class PriceAmountCard extends StatefulWidget { - const PriceAmountCard(this.model); + PriceAmountCard({ + required this.priceModel, + required this.index, + required this.refresh, + }) : model = priceModel.priceAmountModels[index], + total = priceModel.priceAmountModels.length; + final PriceModel priceModel; final PriceAmountModel model; + final int index; + final int total; + // TODO(monsieurtanuki): not elegant, the display was not refreshed when removing an item + final VoidCallback refresh; @override State createState() => _PriceAmountCardState(); @@ -28,9 +39,19 @@ class _PriceAmountCardState extends State { return SmoothCard( child: Column( children: [ - Text(appLocalizations.prices_amount_subtitle), + Text( + '${appLocalizations.prices_amount_subtitle}' + '${widget.total == 1 ? '' : ' (${widget.index + 1}/${widget.total})'}', + ), PriceProductListTile( product: widget.model.product, + trailingIconData: widget.total == 1 ? null : Icons.clear, + onPressed: widget.total == 1 + ? null + : () { + widget.priceModel.priceAmountModels.removeAt(widget.index); + widget.refresh.call(); + }, ), SmoothLargeButtonWithIcon( icon: widget.model.promo @@ -42,43 +63,26 @@ class _PriceAmountCardState extends State { ), ), const SizedBox(height: SMALL_SPACE), - LayoutBuilder( - builder: ( - final BuildContext context, - final BoxConstraints boxConstraints, - ) { - final double columnWidth = - (boxConstraints.maxWidth - LARGE_SPACE) / 2; - final Widget columnPaid = SizedBox( - width: columnWidth, + Row( + children: [ + Expanded( child: PriceAmountField( controller: _controllerPaid, isPaidPrice: true, model: widget.model, ), - ); - if (!widget.model.promo) { - return Align( - alignment: Alignment.centerLeft, - child: columnPaid, - ); - } - final Widget columnWithoutDiscount = SizedBox( - width: columnWidth, - child: PriceAmountField( - controller: _controllerWithoutDiscount, - isPaidPrice: false, - model: widget.model, - ), - ); - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - columnPaid, - columnWithoutDiscount, - ], - ); - }, + ), + const SizedBox(width: LARGE_SPACE), + Expanded( + child: !widget.model.promo + ? Container() + : PriceAmountField( + controller: _controllerWithoutDiscount, + isPaidPrice: false, + model: widget.model, + ), + ), + ], ), ], ), diff --git a/packages/smooth_app/lib/pages/prices/price_model.dart b/packages/smooth_app/lib/pages/prices/price_model.dart index b804400fb74..ae5978231ac 100644 --- a/packages/smooth_app/lib/pages/prices/price_model.dart +++ b/packages/smooth_app/lib/pages/prices/price_model.dart @@ -19,9 +19,11 @@ class PriceModel with ChangeNotifier { }) : _proofType = proofType, _date = DateTime.now(), _locations = locations, - priceAmountModel = PriceAmountModel(product: product); + priceAmountModels = [ + PriceAmountModel(product: product), + ]; - final PriceAmountModel priceAmountModel; + final List priceAmountModels; CropParameters? _cropParameters; @@ -77,9 +79,11 @@ class PriceModel with ChangeNotifier { _checkedCurrency = CurrencySelectorHelper().getSelected(userPreferences.userCurrencyCode); - final String? checkParameters = priceAmountModel.checkParameters(context); - if (checkParameters != null) { - return checkParameters; + for (final PriceAmountModel priceAmountModel in priceAmountModels) { + final String? checkParameters = priceAmountModel.checkParameters(context); + if (checkParameters != null) { + return checkParameters; + } } if (location == null) { @@ -90,20 +94,31 @@ class PriceModel with ChangeNotifier { } /// Adds the related background task. - Future addTask(final BuildContext context) async => - BackgroundTaskAddPrice.addTask( - context: context, - // per receipt - cropObject: cropParameters!, - locationOSMId: location!.osmId, - locationOSMType: location!.osmType, - date: date, - proofType: proofType, - currency: _checkedCurrency, - // per item - barcode: priceAmountModel.product.barcode, - priceIsDiscounted: priceAmountModel.promo, - price: priceAmountModel.checkedPaidPrice, - priceWithoutDiscount: priceAmountModel.checkedPriceWithoutDiscount, - ); + Future addTask(final BuildContext context) async { + final List barcodes = []; + final List pricesAreDiscounted = []; + final List prices = []; + final List pricesWithoutDiscount = []; + for (final PriceAmountModel priceAmountModel in priceAmountModels) { + barcodes.add(priceAmountModel.product.barcode); + pricesAreDiscounted.add(priceAmountModel.promo); + prices.add(priceAmountModel.checkedPaidPrice); + pricesWithoutDiscount.add(priceAmountModel.checkedPriceWithoutDiscount); + } + return BackgroundTaskAddPrice.addTask( + context: context, + // per receipt + cropObject: cropParameters!, + locationOSMId: location!.osmId, + locationOSMType: location!.osmType, + date: date, + proofType: proofType, + currency: _checkedCurrency, + // per item + barcodes: barcodes, + pricesAreDiscounted: pricesAreDiscounted, + prices: prices, + pricesWithoutDiscount: pricesWithoutDiscount, + ); + } } diff --git a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart index 3d238807434..5ec45641130 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart @@ -18,11 +18,11 @@ import 'package:smooth_app/widgets/smooth_scaffold.dart'; /// Product Search Page, for Prices. class PriceProductSearchPage extends StatefulWidget { - const PriceProductSearchPage( + const PriceProductSearchPage({ this.product, - ); + }); - final PriceMetaProduct product; + final PriceMetaProduct? product; // TODO(monsieurtanuki): as a parameter, add a list of barcodes already there: we're not supposed to select twice the same product @override diff --git a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart index 7fdf98d68f9..d66d765db05 100644 --- a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart +++ b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart @@ -5,16 +5,20 @@ import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/database/dao_osm_location.dart'; import 'package:smooth_app/database/local_database.dart'; +import 'package:smooth_app/generic_lib/buttons/smooth_large_button_with_icon.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/locations/osm_location.dart'; import 'package:smooth_app/pages/prices/price_amount_card.dart'; +import 'package:smooth_app/pages/prices/price_amount_model.dart'; import 'package:smooth_app/pages/prices/price_currency_card.dart'; import 'package:smooth_app/pages/prices/price_date_card.dart'; import 'package:smooth_app/pages/prices/price_location_card.dart'; import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/price_model.dart'; +import 'package:smooth_app/pages/prices/price_product_search_page.dart'; import 'package:smooth_app/pages/prices/price_proof_card.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; @@ -85,7 +89,9 @@ class _ProductPriceAddPageState extends State { centerTitle: false, leading: const SmoothBackButton(), title: Text( - appLocalizations.prices_add_a_price, + appLocalizations.prices_add_n_prices( + _model.priceAmountModels.length, + ), ), actions: [ IconButton( @@ -106,7 +112,37 @@ class _ProductPriceAddPageState extends State { const SizedBox(height: LARGE_SPACE), const PriceCurrencyCard(), const SizedBox(height: LARGE_SPACE), - PriceAmountCard(_model.priceAmountModel), + for (int i = 0; i < _model.priceAmountModels.length; i++) + PriceAmountCard( + priceModel: _model, + index: i, + refresh: () => setState(() {}), + ), + SmoothCard( + child: SmoothLargeButtonWithIcon( + text: appLocalizations.prices_add_an_item, + icon: Icons.add, + onPressed: () async { + final PriceMetaProduct? product = + await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => + const PriceProductSearchPage(), + ), + ); + if (product == null) { + return; + } + setState( + () => _model.priceAmountModels.add( + PriceAmountModel( + product: product, + ), + ), + ); + }, + ), + ), // so that the last items don't get hidden by the FAB const SizedBox(height: MINIMUM_TOUCH_SIZE * 2), ], @@ -143,7 +179,11 @@ class _ProductPriceAddPageState extends State { Navigator.of(context).pop(); }, icon: const Icon(Icons.send), - label: Text(appLocalizations.prices_send_the_price), + label: Text( + appLocalizations.prices_send_n_prices( + _model.priceAmountModels.length, + ), + ), ), ), ), From 18505ddc0e09ec7bf6f048dd7b0f1eb7a33a04db Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Sat, 15 Jun 2024 12:27:43 +0200 Subject: [PATCH 09/85] fix: 5371 - less ambiguous currency symbol (#5376) --- .../smooth_app/lib/pages/onboarding/currency_selector.dart | 2 +- .../lib/pages/onboarding/currency_selector_helper.dart | 3 +++ .../smooth_app/lib/pages/prices/price_currency_selector.dart | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/smooth_app/lib/pages/onboarding/currency_selector.dart b/packages/smooth_app/lib/pages/onboarding/currency_selector.dart index 726c3dbce86..84de4dadf12 100644 --- a/packages/smooth_app/lib/pages/onboarding/currency_selector.dart +++ b/packages/smooth_app/lib/pages/onboarding/currency_selector.dart @@ -51,7 +51,7 @@ class CurrencySelector extends StatelessWidget { padding: const EdgeInsets.symmetric( vertical: SMALL_SPACE, ).add(padding ?? EdgeInsets.zero), - child: const Icon(Icons.currency_exchange), + child: Icon(helper.currencyIconData), ), Expanded( flex: 1, diff --git a/packages/smooth_app/lib/pages/onboarding/currency_selector_helper.dart b/packages/smooth_app/lib/pages/onboarding/currency_selector_helper.dart index 169305e83d1..689dfb5527a 100644 --- a/packages/smooth_app/lib/pages/onboarding/currency_selector_helper.dart +++ b/packages/smooth_app/lib/pages/onboarding/currency_selector_helper.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; @@ -13,6 +14,8 @@ class CurrencySelectorHelper { final List _currencyList = List.from(Currency.values); + IconData get currencyIconData => CupertinoIcons.money_dollar_circle; + Future openCurrencySelector({ required final BuildContext context, required final Currency selected, diff --git a/packages/smooth_app/lib/pages/prices/price_currency_selector.dart b/packages/smooth_app/lib/pages/prices/price_currency_selector.dart index 685d34dd826..f0941f22db1 100644 --- a/packages/smooth_app/lib/pages/prices/price_currency_selector.dart +++ b/packages/smooth_app/lib/pages/prices/price_currency_selector.dart @@ -30,7 +30,7 @@ class PriceCurrencySelector extends StatelessWidget { } }, text: selected.getFullName(), - icon: Icons.currency_exchange, + icon: helper.currencyIconData, ); } } From 2a08ab411417aee00cfd79d15393c6aeec97668f Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 15 Jun 2024 17:21:09 +0200 Subject: [PATCH 10/85] Edge to edge mode on Android (#5378) --- packages/smooth_app/lib/main.dart | 13 ++ .../onboarding/consent_analytics_page.dart | 127 +++++------ .../knowledge_panel_page_template.dart | 2 +- .../pages/onboarding/permissions_page.dart | 117 ++++++----- .../pages/onboarding/reinvention_page.dart | 2 +- .../lib/pages/onboarding/scan_example.dart | 84 ++++---- .../lib/pages/onboarding/welcome_page.dart | 197 +++++++++--------- .../lib/pages/product/edit_ocr_page.dart | 56 ++--- .../lib/pages/product/edit_product_page.dart | 6 +- .../lib/pages/product/new_product_page.dart | 2 + .../lib/widgets/smooth_scaffold.dart | 10 +- 11 files changed, 328 insertions(+), 288 deletions(-) diff --git a/packages/smooth_app/lib/main.dart b/packages/smooth_app/lib/main.dart index 79d451e26f8..66332c09516 100644 --- a/packages/smooth_app/lib/main.dart +++ b/packages/smooth_app/lib/main.dart @@ -81,6 +81,8 @@ Future launchSmoothApp({ WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); + _enableEdgeToEdgeMode(); + if (kReleaseMode) { await AnalyticsHelper.initSentry( appRunner: () => runApp(const SmoothApp())); @@ -89,6 +91,17 @@ Future launchSmoothApp({ } } +void _enableEdgeToEdgeMode() { + if (Platform.isAndroid) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + ), + ); + } +} + class SmoothApp extends StatefulWidget { const SmoothApp(); diff --git a/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart b/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart index f096f38151d..acadaf67225 100644 --- a/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -24,72 +26,73 @@ class ConsentAnalyticsPage extends StatelessWidget { final AppLocalizations appLocalizations = AppLocalizations.of(context); return ColoredBox( color: backgroundColor, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - SvgPicture.asset( - 'assets/onboarding/analytics.svg', - width: screenSize.width * .50, - package: AppHelper.APP_PACKAGE, - ), - const SizedBox(height: LARGE_SPACE), - AutoSizeText( - appLocalizations.consent_analytics_title, - maxLines: 2, - style: Theme.of(context) - .textTheme - .displayLarge! - .apply(color: const Color.fromARGB(255, 51, 51, 51)), - textAlign: TextAlign.center, - ), - const SizedBox(height: SMALL_SPACE), - AutoSizeText( - appLocalizations.consent_analytics_body1, - maxLines: 3, - textAlign: TextAlign.center, - style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, - ), - const SizedBox(height: SMALL_SPACE), - AutoSizeText( - appLocalizations.consent_analytics_body2, - maxLines: 3, - textAlign: TextAlign.center, - style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, - ), - ], + child: SafeArea( + bottom: Platform.isAndroid, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + 'assets/onboarding/analytics.svg', + width: screenSize.width * .50, + package: AppHelper.APP_PACKAGE, + ), + const SizedBox(height: LARGE_SPACE), + AutoSizeText( + appLocalizations.consent_analytics_title, + maxLines: 2, + style: Theme.of(context).textTheme.displayLarge!.apply( + color: const Color.fromARGB(255, 51, 51, 51)), + textAlign: TextAlign.center, + ), + const SizedBox(height: SMALL_SPACE), + AutoSizeText( + appLocalizations.consent_analytics_body1, + maxLines: 3, + textAlign: TextAlign.center, + style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, + ), + const SizedBox(height: SMALL_SPACE), + AutoSizeText( + appLocalizations.consent_analytics_body2, + maxLines: 3, + textAlign: TextAlign.center, + style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, + ), + ], + ), ), ), ), - ), - OnboardingBottomBar( - rightButton: _buildButton( - context, - appLocalizations.refuse_button_label, - false, - const Color(0xFFA08D84), - Colors.white, - ), - leftButton: _buildButton( - context, - appLocalizations.authorize_button_label, - true, - Colors.white, - Colors.black, + OnboardingBottomBar( + rightButton: _buildButton( + context, + appLocalizations.refuse_button_label, + false, + const Color(0xFFA08D84), + Colors.white, + ), + leftButton: _buildButton( + context, + appLocalizations.authorize_button_label, + true, + Colors.white, + Colors.black, + ), + backgroundColor: backgroundColor, + semanticsHorizontalOrder: false, ), - backgroundColor: backgroundColor, - semanticsHorizontalOrder: false, - ), - ], + ], + ), ), ); } diff --git a/packages/smooth_app/lib/pages/onboarding/knowledge_panel_page_template.dart b/packages/smooth_app/lib/pages/onboarding/knowledge_panel_page_template.dart index 6a4a68ca5f9..7be4686b503 100644 --- a/packages/smooth_app/lib/pages/onboarding/knowledge_panel_page_template.dart +++ b/packages/smooth_app/lib/pages/onboarding/knowledge_panel_page_template.dart @@ -85,7 +85,7 @@ class _KnowledgePanelPageTemplateState product: _product, onboardingMode: true, ); - return Container( + return ColoredBox( color: widget.backgroundColor, child: SafeArea( bottom: Platform.isAndroid, diff --git a/packages/smooth_app/lib/pages/onboarding/permissions_page.dart b/packages/smooth_app/lib/pages/onboarding/permissions_page.dart index 4006751138d..bfb2b669f48 100644 --- a/packages/smooth_app/lib/pages/onboarding/permissions_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/permissions_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart' hide Listener; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -46,64 +48,65 @@ class _PermissionsPageState extends State { }, child: ColoredBox( color: widget.backgroundColor, - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - LayoutBuilder(builder: - (BuildContext context, BoxConstraints constraints) { - return SizedBox.square( - dimension: constraints.maxWidth * 0.5, - child: Transform.rotate( - angle: -0.2, - child: const animations.BarcodeAnimation(), - ), - ); - }), - const SizedBox(height: LARGE_SPACE), - AutoSizeText( - appLocalizations.permissions_page_title, - maxLines: 2, - style: Theme.of(context) - .textTheme - .displayLarge! - .apply(color: const Color.fromARGB(255, 51, 51, 51)), - textAlign: TextAlign.center, - ), - const SizedBox(height: SMALL_SPACE), - AutoSizeText( - appLocalizations.permissions_page_body1, - maxLines: 2, - textAlign: TextAlign.center, - style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, - ), - const SizedBox(height: MEDIUM_SPACE), - AutoSizeText( - appLocalizations.permissions_page_body2, - maxLines: 3, - textAlign: TextAlign.center, - style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, - ), - ], + child: SafeArea( + bottom: Platform.isAndroid, + child: Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + LayoutBuilder(builder: + (BuildContext context, BoxConstraints constraints) { + return SizedBox.square( + dimension: constraints.maxWidth * 0.5, + child: Transform.rotate( + angle: -0.2, + child: const animations.BarcodeAnimation(), + ), + ); + }), + const SizedBox(height: LARGE_SPACE), + AutoSizeText( + appLocalizations.permissions_page_title, + maxLines: 2, + style: Theme.of(context).textTheme.displayLarge!.apply( + color: const Color.fromARGB(255, 51, 51, 51)), + textAlign: TextAlign.center, + ), + const SizedBox(height: SMALL_SPACE), + AutoSizeText( + appLocalizations.permissions_page_body1, + maxLines: 2, + textAlign: TextAlign.center, + style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, + ), + const SizedBox(height: MEDIUM_SPACE), + AutoSizeText( + appLocalizations.permissions_page_body2, + maxLines: 3, + textAlign: TextAlign.center, + style: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, + ), + ], + ), + ), + )), + OnboardingBottomBar( + rightButton: _IgnoreButton( + onPermissionIgnored: () => _moveToNextScreen(context), + ), + leftButton: _AskPermissionButton( + onPermissionIgnored: () => _moveToNextScreen(context), ), - ), - )), - OnboardingBottomBar( - rightButton: _IgnoreButton( - onPermissionIgnored: () => _moveToNextScreen(context), - ), - leftButton: _AskPermissionButton( - onPermissionIgnored: () => _moveToNextScreen(context), - ), - backgroundColor: widget.backgroundColor, - semanticsHorizontalOrder: false, - ) - ], + backgroundColor: widget.backgroundColor, + semanticsHorizontalOrder: false, + ) + ], + ), ), ), ); diff --git a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart index 98964256e8c..a60ab501412 100644 --- a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart @@ -28,7 +28,7 @@ class ReinventionPage extends StatelessWidget { final Size screenSize = MediaQuery.sizeOf(context); final double animHeight = 352.0 * screenSize.width / 375.0; - return Container( + return ColoredBox( color: backgroundColor, child: SafeArea( bottom: false, diff --git a/packages/smooth_app/lib/pages/onboarding/scan_example.dart b/packages/smooth_app/lib/pages/onboarding/scan_example.dart index 5eb5d1b9b74..52646e02f03 100644 --- a/packages/smooth_app/lib/pages/onboarding/scan_example.dart +++ b/packages/smooth_app/lib/pages/onboarding/scan_example.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -18,49 +20,53 @@ class ScanExample extends StatelessWidget { Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); final Size screenSize = MediaQuery.sizeOf(context); - return Container( + return ColoredBox( color: backgroundColor, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Used for spacing - EMPTY_WIDGET, - Padding( - padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SvgPicture.asset( - 'assets/onboarding/scan.svg', - height: screenSize.height * .50, - package: AppHelper.APP_PACKAGE, - ), - Padding( - padding: const EdgeInsetsDirectional.only(top: SMALL_SPACE), - child: SizedBox( - height: screenSize.height * .15, - child: AutoSizeText( - appLocalizations.offUtility, - maxLines: 2, - style: Theme.of(context) - .textTheme - .displayLarge! - .wellSpaced - .apply(color: const Color.fromARGB(255, 51, 51, 51)), + child: SafeArea( + bottom: Platform.isAndroid, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Used for spacing + EMPTY_WIDGET, + Padding( + padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/onboarding/scan.svg', + height: screenSize.height * .50, + package: AppHelper.APP_PACKAGE, + ), + Padding( + padding: const EdgeInsetsDirectional.only(top: SMALL_SPACE), + child: SizedBox( + height: screenSize.height * .15, + child: AutoSizeText( + appLocalizations.offUtility, + maxLines: 2, + style: Theme.of(context) + .textTheme + .displayLarge! + .wellSpaced + .apply( + color: const Color.fromARGB(255, 51, 51, 51)), + ), ), ), - ), - ], + ], + ), + ), + NextButton( + OnboardingPage.SCAN_EXAMPLE, + backgroundColor: backgroundColor, + nextKey: const Key('nextAfterScanExample'), ), - ), - NextButton( - OnboardingPage.SCAN_EXAMPLE, - backgroundColor: backgroundColor, - nextKey: const Key('nextAfterScanExample'), - ), - ], + ], + ), ), ); } diff --git a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart index da5b9b8224f..736f8ba6425 100644 --- a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -28,116 +30,119 @@ class WelcomePage extends StatelessWidget { backgroundColor: backgroundColor, brightness: Brightness.dark, resizeToAvoidBottomInset: false, - body: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - flex: 1, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), - child: ListView( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(height: screenSize.height * .05), - SvgPicture.asset( - 'assets/onboarding/title.svg', - height: screenSize.height * .10, - package: AppHelper.APP_PACKAGE, - ), - SvgPicture.asset( - 'assets/onboarding/globe.svg', - height: screenSize.height * .20, - package: AppHelper.APP_PACKAGE, - ), - Padding( - padding: - const EdgeInsetsDirectional.only(top: SMALL_SPACE), - child: SizedBox( - height: screenSize.height * .15, - child: AutoSizeText( - appLocalizations.whatIsOff, - style: headlineStyle, - maxLines: 3, - textAlign: TextAlign.center, - ), + body: SafeArea( + bottom: Platform.isAndroid, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + flex: 1, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), + child: ListView( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: screenSize.height * .05), + SvgPicture.asset( + 'assets/onboarding/title.svg', + height: screenSize.height * .10, + package: AppHelper.APP_PACKAGE, ), - ), - ], - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - appLocalizations.onboarding_country_chooser_label, - style: bodyTextStyle, - ), - Padding( - padding: - const EdgeInsets.symmetric(vertical: MEDIUM_SPACE), - child: Ink( - decoration: BoxDecoration( - border: Border.fromBorderSide( - BorderSide( - color: theme.colorScheme.inversePrimary, - width: 1, - ), + SvgPicture.asset( + 'assets/onboarding/globe.svg', + height: screenSize.height * .20, + package: AppHelper.APP_PACKAGE, + ), + Padding( + padding: const EdgeInsetsDirectional.only( + top: SMALL_SPACE), + child: SizedBox( + height: screenSize.height * .15, + child: AutoSizeText( + appLocalizations.whatIsOff, + style: headlineStyle, + maxLines: 3, + textAlign: TextAlign.center, ), - borderRadius: ROUNDED_BORDER_RADIUS, - color: theme.colorScheme.onPrimary, ), - child: SizedBox( - width: double.infinity, - child: CountrySelector( - forceCurrencyChange: true, - padding: const EdgeInsets.symmetric( - horizontal: SMALL_SPACE, + ), + ], + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + appLocalizations.onboarding_country_chooser_label, + style: bodyTextStyle, + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: MEDIUM_SPACE), + child: Ink( + decoration: BoxDecoration( + border: Border.fromBorderSide( + BorderSide( + color: theme.colorScheme.inversePrimary, + width: 1, + ), ), - inkWellBorderRadius: ROUNDED_BORDER_RADIUS, - icon: Container( - height: double.infinity, - decoration: BoxDecoration( - color: theme.primaryColor, - borderRadius: ROUNDED_BORDER_RADIUS, + borderRadius: ROUNDED_BORDER_RADIUS, + color: theme.colorScheme.onPrimary, + ), + child: SizedBox( + width: double.infinity, + child: CountrySelector( + forceCurrencyChange: true, + padding: const EdgeInsets.symmetric( + horizontal: SMALL_SPACE, ), - child: AspectRatio( - aspectRatio: 1.0, - child: Icon( - Icons.edit, - color: Colors.white.withOpacity(0.9), + inkWellBorderRadius: ROUNDED_BORDER_RADIUS, + icon: Container( + height: double.infinity, + decoration: BoxDecoration( + color: theme.primaryColor, + borderRadius: ROUNDED_BORDER_RADIUS, + ), + child: AspectRatio( + aspectRatio: 1.0, + child: Icon( + Icons.edit, + color: Colors.white.withOpacity(0.9), + ), ), ), + textStyle: TextStyle(color: theme.primaryColor), ), - textStyle: TextStyle(color: theme.primaryColor), ), ), ), - ), - Padding( - padding: const EdgeInsetsDirectional.only( - bottom: VERY_SMALL_SPACE, - ), - child: Text( - appLocalizations.country_selection_explanation, - style: bodyTextStyle, + Padding( + padding: const EdgeInsetsDirectional.only( + bottom: VERY_SMALL_SPACE, + ), + child: Text( + appLocalizations.country_selection_explanation, + style: bodyTextStyle, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), - ), - NextButton( - OnboardingPage.WELCOME, - backgroundColor: backgroundColor, - nextKey: const Key('nextAfterWelcome'), - ), - ], + NextButton( + OnboardingPage.WELCOME, + backgroundColor: backgroundColor, + nextKey: const Key('nextAfterWelcome'), + ), + ], + ), ), ); } diff --git a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr_page.dart index 3548e33cb0a..4331a249eea 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr_page.dart @@ -260,16 +260,21 @@ class _EditOcrPageState extends State with UpToDateMixin { ), Flexible( flex: 1, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, - borderRadius: const BorderRadiusDirectional.only( - topStart: ANGULAR_RADIUS, - topEnd: ANGULAR_RADIUS, - )), + color: Theme.of(context).colorScheme.background, + borderRadius: const BorderRadiusDirectional.only( + topStart: ANGULAR_RADIUS, + topEnd: ANGULAR_RADIUS, + ), + ), child: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.all(LARGE_SPACE), + padding: const EdgeInsetsDirectional.only( + start: LARGE_SPACE, + end: LARGE_SPACE, + top: LARGE_SPACE, + ), child: Column( children: [ if (!_multilingualHelper.isMonolingual()) @@ -321,31 +326,30 @@ class _EditOcrPageState extends State with UpToDateMixin { iconData: Icons.add_a_photo, ), ), - const SizedBox(height: MEDIUM_SPACE), - SmoothActionButtonsBar( - axis: Axis.horizontal, - negativeAction: SmoothActionButton( - text: appLocalizations.cancel, - onPressed: () => Navigator.pop(context), - ), - positiveAction: SmoothActionButton( - text: appLocalizations.save, - onPressed: () async { - await _updateText(); - if (!mounted) { - return; - } - Navigator.pop(context); - }, - ), - ), - const SizedBox(height: MEDIUM_SPACE), ], ), ), ), ), ), + SmoothActionButtonsBar( + axis: Axis.horizontal, + negativeAction: SmoothActionButton( + text: appLocalizations.cancel, + onPressed: () => Navigator.pop(context), + ), + positiveAction: SmoothActionButton( + text: appLocalizations.save, + onPressed: () async { + await _updateText(); + if (!mounted) { + return; + } + Navigator.pop(context); + }, + ), + ), + SizedBox(height: MediaQuery.paddingOf(context).bottom), ], ), ); diff --git a/packages/smooth_app/lib/pages/product/edit_product_page.dart b/packages/smooth_app/lib/pages/product/edit_product_page.dart index fe41b9d5615..610ae38ab5c 100644 --- a/packages/smooth_app/lib/pages/product/edit_product_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_product_page.dart @@ -76,8 +76,9 @@ class _EditProductPageState extends State with UpToDateMixin { theme.textTheme.titleLarge?.fontSize?.clamp(13.0, 17.0) ?? 13.0, maxLines: !_barcodeVisibleInAppbar ? 2 : 1, - style: theme.textTheme.titleLarge - ?.copyWith(fontWeight: FontWeight.w500), + style: theme.textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.w500, + ), ), if (barcode.isNotEmpty) AnimatedContainer( @@ -87,6 +88,7 @@ class _EditProductPageState extends State with UpToDateMixin { barcode, style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.normal, + height: 0.9, ), ), ), diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index d5e70156a3c..f16cd8f68c8 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -258,6 +258,8 @@ class _ProductPageState extends State if (questionsLayout == ProductQuestionsLayout.banner) // assuming it's tall enough in order to go above the banner const SizedBox(height: 4 * VERY_LARGE_SPACE), + // Space for the navigation bar + SizedBox(height: MediaQuery.paddingOf(context).bottom), ], ), ); diff --git a/packages/smooth_app/lib/widgets/smooth_scaffold.dart b/packages/smooth_app/lib/widgets/smooth_scaffold.dart index ae5b4c73d2e..66e355fa3d0 100644 --- a/packages/smooth_app/lib/widgets/smooth_scaffold.dart +++ b/packages/smooth_app/lib/widgets/smooth_scaffold.dart @@ -162,18 +162,20 @@ class SmoothScaffoldState extends ScaffoldState { switch (brightness) { case Brightness.dark: - return const SystemUiOverlayStyle( + return SystemUiOverlayStyle( statusBarIconBrightness: Brightness.dark, statusBarBrightness: Brightness.light, - systemNavigationBarContrastEnforced: false, + systemNavigationBarContrastEnforced: + !Platform.isAndroid ? false : null, ); case Brightness.light: default: - return const SystemUiOverlayStyle( + return SystemUiOverlayStyle( statusBarIconBrightness: Brightness.light, statusBarBrightness: Brightness.dark, - systemNavigationBarContrastEnforced: false, + systemNavigationBarContrastEnforced: + !Platform.isAndroid ? false : null, ); } } From 35a4ab03c027406af6946ed024f7d53c3e86d322 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Sat, 15 Jun 2024 17:23:04 +0200 Subject: [PATCH 11/85] feat: prices - barcode reader for additional products (#5381) New file: * `price_scan_page.dart`: Page showing the camera feed and decoding the first barcode, for Prices. Impacted files: * `app_en.arb`: added 1 "barcode reader" label * `app_fr.arb`: added 1 "barcode reader" label * `camera_scan_page.dart`: minor refactoring * `price_product_search_page.dart`: added a FAB towards the new barcode reader page --- packages/smooth_app/lib/l10n/app_en.arb | 1 + packages/smooth_app/lib/l10n/app_fr.arb | 1 + .../prices/price_product_search_page.dart | 115 +++++++++++------- .../lib/pages/prices/price_scan_page.dart | 53 ++++++++ .../lib/pages/scan/camera_scan_page.dart | 29 +++-- 5 files changed, 143 insertions(+), 56 deletions(-) create mode 100644 packages/smooth_app/lib/pages/prices/price_scan_page.dart diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 8c378f6d3d2..7c55331791d 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1688,6 +1688,7 @@ } } }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index bde1e1bf2ba..1b8811a31c8 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1688,6 +1688,7 @@ } } }, + "prices_barcode_reader_action": "Lecteur de code-barres", "prices_view_prices": "Voir les prix", "prices_list_length_one_page": "{count,plural, =0{Aucun prix} =1{Un seul prix} other{Tous les {count} prix}}", "@prices_list_length_one_page": { diff --git a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart index 5ec45641130..74a4933cb59 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart @@ -10,8 +10,10 @@ import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/loading_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; +import 'package:smooth_app/helpers/camera_helper.dart'; import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/price_product_list_tile.dart'; +import 'package:smooth_app/pages/prices/price_scan_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -48,7 +50,6 @@ class _PriceProductSearchPageState extends State { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); - final LocalDatabase localDatabase = context.read(); // TODO(monsieurtanuki): add WillPopScope2 return SmoothScaffold( appBar: SmoothAppBar( @@ -56,6 +57,13 @@ class _PriceProductSearchPageState extends State { leading: const SmoothBackButton(), title: Text(appLocalizations.prices_barcode_search_title), ), + floatingActionButton: !CameraHelper.hasACamera + ? null + : FloatingActionButton.extended( + onPressed: () async => _scan(context), + label: Text(appLocalizations.prices_barcode_reader_action), + icon: const Icon(Icons.barcode_reader), + ), body: SingleChildScrollView( padding: const EdgeInsets.all(LARGE_SPACE), child: Column( @@ -67,46 +75,8 @@ class _PriceProductSearchPageState extends State { controller: _controller, hintText: _barcodeHint, textInputType: _textInputType, - onChanged: (_) async { - final String barcode = _controller.text; - final String cleanBarcode = _getCleanBarcode(barcode); - if (barcode != cleanBarcode) { - setState(() => _controller.text = cleanBarcode); - return; - } - - if (_product != null) { - setState( - () => _product = null, - ); - } - - final Product? product = await _localSearch( - barcode, - localDatabase, - ); - if (product != null) { - setState( - () => _product = PriceMetaProduct.product(product), - ); - return; - } - }, - onFieldSubmitted: (_) async { - final String barcode = _controller.text; - if (barcode.isEmpty) { - return; - } - - final Product? product = await _serverSearch( - barcode, - localDatabase, - context, - ); - if (product != null) { - setState(() => _product = PriceMetaProduct.product(product)); - } - }, + onChanged: (_) async => _onChanged(context), + onFieldSubmitted: (_) async => _onFieldSubmitted(context), prefixIcon: const Icon(CupertinoIcons.barcode), textInputAction: TextInputAction.search, ), @@ -175,4 +145,67 @@ class _PriceProductSearchPageState extends State { } return buffer.toString(); } + + Future _onChanged(final BuildContext context) async { + final String barcode = _controller.text; + final String cleanBarcode = _getCleanBarcode(barcode); + if (barcode != cleanBarcode) { + setState(() => _controller.text = cleanBarcode); + return; + } + + if (_product != null) { + setState(() => _product = null); + } + + final LocalDatabase localDatabase = context.read(); + final Product? product = await _localSearch( + barcode, + localDatabase, + ); + if (product != null) { + setState(() => _product = PriceMetaProduct.product(product)); + return; + } + } + + Future _onFieldSubmitted(final BuildContext context) async { + final String barcode = _controller.text; + if (barcode.isEmpty) { + return; + } + + final LocalDatabase localDatabase = context.read(); + final Product? product = await _serverSearch( + barcode, + localDatabase, + context, + ); + if (product != null) { + setState(() => _product = PriceMetaProduct.product(product)); + } + } + + Future _scan(final BuildContext context) async { + final String? barcode = await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => const PriceScanPage(), + ), + ); + if (barcode == null) { + return; + } + _controller.text = barcode; + if (!context.mounted) { + return; + } + await _onChanged(context); + if (_product != null) { + return; + } + if (!context.mounted) { + return; + } + await _onFieldSubmitted(context); + } } diff --git a/packages/smooth_app/lib/pages/prices/price_scan_page.dart b/packages/smooth_app/lib/pages/prices/price_scan_page.dart new file mode 100644 index 00000000000..1b12cabd097 --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_scan_page.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:matomo_tracker/matomo_tracker.dart'; +import 'package:smooth_app/helpers/analytics_helper.dart'; +import 'package:smooth_app/helpers/camera_helper.dart'; +import 'package:smooth_app/helpers/global_vars.dart'; +import 'package:smooth_app/helpers/haptic_feedback_helper.dart'; +import 'package:smooth_app/pages/scan/camera_scan_page.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Page showing the camera feed and decoding the first barcode, for Prices. +class PriceScanPage extends StatefulWidget { + const PriceScanPage(); + + @override + State createState() => _PriceScanPageState(); +} + +class _PriceScanPageState extends State + with TraceableClientMixin { + // Mutual exclusion needed: we typically receive several times the same + // barcode and the `pop` would be called several times and cause an error like + // `Failed assertion: line 5277 pos 12: '!_debugLocked': is not true.` + bool _mutex = false; + + @override + String get actionName => + 'Opened ${GlobalVars.barcodeScanner.getType()}_page for price'; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + return SmoothScaffold( + body: GlobalVars.barcodeScanner.getScanner( + onScan: (final String barcode) async { + if (_mutex) { + return false; + } + _mutex = true; + Navigator.of(context).pop(barcode); + return true; + }, + hapticFeedback: () => SmoothHapticFeedback.click(), + onCameraFlashError: CameraScannerPage.onCameraFlashError, + trackCustomEvent: AnalyticsHelper.trackCustomEvent, + hasMoreThanOneCamera: CameraHelper.hasMoreThanOneCamera, + toggleCameraModeTooltip: appLocalizations.camera_toggle_camera, + toggleFlashModeTooltip: appLocalizations.camera_toggle_flash, + contentPadding: null, + ), + ); + } +} diff --git a/packages/smooth_app/lib/pages/scan/camera_scan_page.dart b/packages/smooth_app/lib/pages/scan/camera_scan_page.dart index f9442cae2cf..4a6af676926 100644 --- a/packages/smooth_app/lib/pages/scan/camera_scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/camera_scan_page.dart @@ -19,10 +19,21 @@ class CameraScannerPage extends StatefulWidget { const CameraScannerPage(); @override - CameraScannerPageState createState() => CameraScannerPageState(); + State createState() => _CameraScannerPageState(); + + static Future onCameraFlashError(BuildContext context) async { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + return showDialog( + context: context, + builder: (_) => SmoothAlertDialog( + title: appLocalizations.camera_flash_error_dialog_title, + body: Text(appLocalizations.camera_flash_error_dialog_message), + ), + ); + } } -class CameraScannerPageState extends State +class _CameraScannerPageState extends State with TraceableClientMixin { final GlobalKey> _headerKey = GlobalKey(); @@ -87,7 +98,7 @@ class CameraScannerPageState extends State GlobalVars.barcodeScanner.getScanner( onScan: _onNewBarcodeDetected, hapticFeedback: () => SmoothHapticFeedback.click(), - onCameraFlashError: _onCameraFlashError, + onCameraFlashError: CameraScannerPage.onCameraFlashError, trackCustomEvent: AnalyticsHelper.trackCustomEvent, hasMoreThanOneCamera: CameraHelper.hasMoreThanOneCamera, toggleCameraModeTooltip: appLocalizations.camera_toggle_camera, @@ -115,16 +126,4 @@ class CameraScannerPageState extends State _userPreferences.incrementScanCount(); return true; } - - void _onCameraFlashError(BuildContext context) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - - showDialog( - context: context, - builder: (_) => SmoothAlertDialog( - title: appLocalizations.camera_flash_error_dialog_title, - body: Text(appLocalizations.camera_flash_error_dialog_message), - ), - ); - } } From 3b88ac07092e52fe030e18e8b2c0b8409ee7b2e3 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 15 Jun 2024 17:59:04 +0200 Subject: [PATCH 12/85] Onboarding with main/home page from V2 (#5382) --- .../assets/onboarding/birthday-cake.svg | 32 -- .../smooth_app/assets/onboarding/cloud.svg | 11 + .../assets/onboarding/reinvention.svg | 36 -- .../lib/data_models/onboarding_loader.dart | 2 +- packages/smooth_app/lib/l10n/app_en.arb | 12 +- .../onboarding/onboarding_flow_navigator.dart | 8 +- .../pages/onboarding/reinvention_page.dart | 378 +++++++++++------- .../v2/onboarding_bottom_hills.dart | 114 ++++++ .../smooth_app/lib/widgets/smooth_text.dart | 28 ++ 9 files changed, 405 insertions(+), 216 deletions(-) delete mode 100644 packages/smooth_app/assets/onboarding/birthday-cake.svg create mode 100644 packages/smooth_app/assets/onboarding/cloud.svg delete mode 100644 packages/smooth_app/assets/onboarding/reinvention.svg create mode 100644 packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart diff --git a/packages/smooth_app/assets/onboarding/birthday-cake.svg b/packages/smooth_app/assets/onboarding/birthday-cake.svg deleted file mode 100644 index a26a2c391ec..00000000000 --- a/packages/smooth_app/assets/onboarding/birthday-cake.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/smooth_app/assets/onboarding/cloud.svg b/packages/smooth_app/assets/onboarding/cloud.svg new file mode 100644 index 00000000000..8127531dc4e --- /dev/null +++ b/packages/smooth_app/assets/onboarding/cloud.svg @@ -0,0 +1,11 @@ + + + Vector + + + + + + + + \ No newline at end of file diff --git a/packages/smooth_app/assets/onboarding/reinvention.svg b/packages/smooth_app/assets/onboarding/reinvention.svg deleted file mode 100644 index 641f75117ca..00000000000 --- a/packages/smooth_app/assets/onboarding/reinvention.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/smooth_app/lib/data_models/onboarding_loader.dart b/packages/smooth_app/lib/data_models/onboarding_loader.dart index 9ba991956e8..2b8602e0850 100644 --- a/packages/smooth_app/lib/data_models/onboarding_loader.dart +++ b/packages/smooth_app/lib/data_models/onboarding_loader.dart @@ -44,7 +44,7 @@ class OnboardingLoader { } return; case OnboardingPage.NOT_STARTED: - case OnboardingPage.REINVENTION: + case OnboardingPage.HOME_PAGE: case OnboardingPage.SCAN_EXAMPLE: case OnboardingPage.HEALTH_CARD_EXAMPLE: case OnboardingPage.ECO_CARD_EXAMPLE: diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 7c55331791d..7cc4f69934a 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1092,14 +1092,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart index 9cd670c5ee9..5cccb33335e 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart @@ -18,7 +18,7 @@ import 'package:smooth_app/widgets/will_pop_scope.dart'; enum OnboardingPage { NOT_STARTED, - REINVENTION, + HOME_PAGE, WELCOME, SCAN_EXAMPLE, HEALTH_CARD_EXAMPLE, @@ -52,7 +52,7 @@ enum OnboardingPage { Color getBackgroundColor() { switch (this) { case OnboardingPage.NOT_STARTED: - case OnboardingPage.REINVENTION: + case OnboardingPage.HOME_PAGE: return const Color(0xFFDFF4FF); case OnboardingPage.WELCOME: return const Color(0xFFFCFCFC); @@ -79,8 +79,8 @@ enum OnboardingPage { final Color backgroundColor = getBackgroundColor(); switch (this) { case OnboardingPage.NOT_STARTED: - case OnboardingPage.REINVENTION: - return ReinventionPage(backgroundColor); + case OnboardingPage.HOME_PAGE: + return const OnboardingHomePage(); case OnboardingPage.WELCOME: return WelcomePage(backgroundColor); case OnboardingPage.SCAN_EXAMPLE: diff --git a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart index a60ab501412..690c8833d61 100644 --- a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart @@ -1,171 +1,277 @@ -import 'dart:io'; - -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; import 'package:rive/rive.dart'; -import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/generic_lib/duration_constants.dart'; -import 'package:smooth_app/helpers/app_helper.dart'; -import 'package:smooth_app/pages/onboarding/next_button.dart'; +import 'package:smooth_app/data_models/onboarding_loader.dart'; +import 'package:smooth_app/data_models/preferences/user_preferences.dart'; +import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/pages/onboarding/onboarding_flow_navigator.dart'; +import 'package:smooth_app/pages/onboarding/v2/onboarding_bottom_hills.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/widgets/smooth_text.dart'; /// Onboarding page: "reinvention" -class ReinventionPage extends StatelessWidget { - const ReinventionPage(this.backgroundColor); - - final Color backgroundColor; +class OnboardingHomePage extends StatelessWidget { + const OnboardingHomePage({super.key}); @override Widget build(BuildContext context) { - const double muchTooBigFontSize = 150; - final AppLocalizations appLocalizations = AppLocalizations.of(context); - final TextStyle headlineStyle = Theme.of(context) - .textTheme - .displayMedium! - .copyWith(fontSize: muchTooBigFontSize); - final Size screenSize = MediaQuery.sizeOf(context); - final double animHeight = 352.0 * screenSize.width / 375.0; - - return ColoredBox( - color: backgroundColor, - child: SafeArea( - bottom: false, + return Scaffold( + backgroundColor: const Color(0xFFE3F3FE), + body: Provider.value( + value: OnboardingConfig._(MediaQuery.of(context)), child: Stack( children: [ - Positioned( - left: 0.0, - right: 0.0, - bottom: 0.0, - top: screenSize.height * 0.75, - child: _Background( - screenWidth: screenSize.width, - ), - ), - Positioned( - left: 0.0, - right: 0.0, - bottom: 0.0, - child: RepaintBoundary( - child: SizedBox( - width: screenSize.width, - height: animHeight, - child: const RiveAnimation.asset( - 'assets/onboarding/onboarding.riv', - artboard: 'Reinvention', - animations: ['Loop'], - alignment: Alignment.bottomCenter, - ), - ), - ), + const _OnboardingWelcomePageContent(), + OnboardingBottomHills( + onTap: () async { + final UserPreferences userPreferences = + context.read(); + final LocalDatabase localDatabase = + context.read(); + + await OnboardingLoader(localDatabase) + .runAtNextTime(OnboardingPage.HOME_PAGE, context); + if (context.mounted) { + await OnboardingFlowNavigator(userPreferences).navigateToPage( + context, + OnboardingPage.HOME_PAGE.getNextPage(), + ); + } + }, ), - Positioned( - top: 0.0, - left: 0.0, - right: 0.0, - bottom: animHeight - 20.0, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Flexible( - flex: 30, - child: Padding( - padding: const EdgeInsets.all(SMALL_SPACE), - child: Center( - child: AutoSizeText( - appLocalizations.onboarding_reinventing_text1, - style: headlineStyle, - maxLines: 3, - textAlign: TextAlign.center, - ), - ), - ), - ), - Flexible( - flex: 15, - child: SvgPicture.asset( - 'assets/onboarding/birthday-cake.svg', - package: AppHelper.APP_PACKAGE, - ), - ), - Flexible( - flex: 30, - child: Padding( - padding: const EdgeInsets.all(SMALL_SPACE), - child: Center( - child: AutoSizeText( - appLocalizations.onboarding_reinventing_text2, - style: headlineStyle, - maxLines: 3, - textAlign: TextAlign.center, - ), - ), - ), - ), - Flexible( - flex: 25, - child: SvgPicture.asset( - 'assets/onboarding/title.svg', - package: AppHelper.APP_PACKAGE, - ), - ), - ], + ], + ), + ), + ); + } +} + +class _OnboardingWelcomePageContent extends StatelessWidget { + const _OnboardingWelcomePageContent(); + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final double fontMultiplier = OnboardingConfig.of(context).fontMultiplier; + final double hillsHeight = OnboardingBottomHills.height(context); + + return Padding( + padding: EdgeInsetsDirectional.only( + top: hillsHeight * 0.5 + MediaQuery.viewPaddingOf(context).top, + bottom: hillsHeight, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 15, + child: Text( + appLocalizations.onboarding_home_welcome_text1, + style: TextStyle( + fontSize: 45 * fontMultiplier, + fontWeight: FontWeight.bold, ), + textAlign: TextAlign.center, ), - Positioned( - bottom: 0, - child: SafeArea( - bottom: !Platform.isIOS, - child: const NextButton( - OnboardingPage.REINVENTION, - backgroundColor: null, - nextKey: Key('nextAfterReinvention'), + ), + const Expanded( + flex: 37, + child: _SunAndCloud(), + ), + Expanded( + flex: 45, + child: FractionallySizedBox( + widthFactor: 0.65, + child: Align( + alignment: const Alignment(0, -0.2), + child: OnboardingText( + text: appLocalizations.onboarding_home_welcome_text2, ), ), ), - ], - ), + ), + ], ), ); } } -class _Background extends StatelessWidget { - const _Background({required this.screenWidth}); +class _SunAndCloud extends StatefulWidget { + const _SunAndCloud(); + + @override + State<_SunAndCloud> createState() => _SunAndCloudState(); +} + +class _SunAndCloudState extends State<_SunAndCloud> + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _animation; - final double screenWidth; + @override + void initState() { + super.initState(); + _controller = + AnimationController(vsync: this, duration: const Duration(seconds: 2)) + ..addListener(() => setState(() {})); + _animation = Tween( + begin: -1.0, + end: 1.0, + ).animate(_controller); + _controller.repeat(reverse: true); + } @override Widget build(BuildContext context) { - return SizedBox.expand( - child: RepaintBoundary( - child: Stack( + final TextDirection textDirection = Directionality.of(context); + + return RepaintBoundary( + child: LayoutBuilder(builder: ( + BuildContext context, + BoxConstraints constraints, + ) { + return Stack( children: [ - AnimatedPositioned( - bottom: 0.0, - right: 0.0, - width: screenWidth * 0.808, - duration: SmoothAnimationsDuration.short, - child: SvgPicture.asset( - 'assets/onboarding/hill_end.svg', - fit: BoxFit.fill, - ), + Positioned.directional( + top: constraints.maxHeight * 0.3, + bottom: constraints.maxHeight * 0.2, + start: (_animation.value * 161.0) * 0.3, + textDirection: textDirection, + child: SvgPicture.asset('assets/onboarding/cloud.svg'), ), - AnimatedPositioned( - bottom: 0.0, - left: 0.0, - width: screenWidth * 0.855, - duration: SmoothAnimationsDuration.short, - child: SvgPicture.asset( - 'assets/onboarding/hill_start.svg', - fit: BoxFit.fill, + const Align( + alignment: Alignment.center, + child: RiveAnimation.asset( + 'assets/animations/off.riv', + artboard: 'Success', + animations: ['Timeline 1'], ), - ) + ), + Positioned.directional( + top: constraints.maxHeight * 0.22, + bottom: constraints.maxHeight * 0.35, + end: (_animation.value * 40.0) - 31, + textDirection: textDirection, + child: SvgPicture.asset('assets/onboarding/cloud.svg'), + ), ], - ), + ); + }), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } +} + +class OnboardingText extends StatelessWidget { + const OnboardingText({ + required this.text, + this.margin, + super.key, + }); + + final String text; + final EdgeInsetsGeometry? margin; + + @override + Widget build(BuildContext context) { + double fontMultiplier; + try { + fontMultiplier = OnboardingConfig.of(context).fontMultiplier; + } catch (_) { + fontMultiplier = + OnboardingConfig.computeFontMultiplier(MediaQuery.of(context)); + } + + final Color backgroundColor = + Theme.of(context).extension()!.orange; + + return RichText( + text: TextSpan( + children: _extractChunks().map(((String text, bool highlighted) el) { + if (el.$2) { + return _createSpan( + el.$1, + 30 * fontMultiplier, + backgroundColor, + ); + } else { + return TextSpan(text: el.$1); + } + }).toList(growable: false), + style: DefaultTextStyle.of(context).style.copyWith( + fontSize: 30 * fontMultiplier, + height: 1.53, + fontWeight: FontWeight.w600, + ), ), + textAlign: TextAlign.center, ); } + + Iterable<(String, bool)> _extractChunks() { + final Iterable matches = + RegExp(r'\*\*(.*?)\*\*').allMatches(text); + + if (matches.length <= 1) { + return <(String, bool)>[(text, false)]; + } + + final List<(String, bool)> chunks = <(String, bool)>[]; + + int lastMatch = 0; + + for (final RegExpMatch match in matches) { + if (matches.first.start > 0) { + chunks.add((text.substring(lastMatch, match.start), false)); + } + + chunks.add((text.substring(match.start + 2, match.end - 2), true)); + lastMatch = match.end; + } + + if (lastMatch < text.length) { + chunks.add((text.substring(lastMatch), false)); + } + + return chunks; + } + + WidgetSpan _createSpan(String text, double fontSize, Color backgroundColor) => + HighlightedTextSpan( + text: text, + textStyle: TextStyle( + color: Colors.white, + fontSize: fontSize, + fontWeight: FontWeight.w700, + ), + padding: const EdgeInsetsDirectional.only( + top: 1.0, + bottom: 5.0, + start: 15.0, + end: 15.0, + ), + margin: margin ?? const EdgeInsetsDirectional.symmetric(vertical: 2.5), + backgroundColor: backgroundColor, + radius: 30.0, + ); +} + +// TODO(g123k): Move elsewhere when the onboarding will be redesigned +class OnboardingConfig { + OnboardingConfig._(MediaQueryData mediaQuery) + : fontMultiplier = computeFontMultiplier(mediaQuery); + final double fontMultiplier; + + static double computeFontMultiplier(MediaQueryData mediaQuery) => + ((mediaQuery.size.width * 45) / 428) / 45; + + static OnboardingConfig of(BuildContext context) => + context.watch(); } diff --git a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart new file mode 100644 index 00000000000..49b3b784299 --- /dev/null +++ b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart @@ -0,0 +1,114 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; + +class OnboardingBottomHills extends StatelessWidget { + const OnboardingBottomHills({ + required this.onTap, + super.key, + }); + + final VoidCallback onTap; + + static double height(BuildContext context) { + final double screenHeight = MediaQuery.sizeOf(context).height; + final double bottomPadding = MediaQuery.viewPaddingOf(context).bottom; + return screenHeight * (0.12 + (bottomPadding / screenHeight)); + } + + @override + Widget build(BuildContext context) { + final TextDirection textDirection = Directionality.of(context); + final double bottomPadding = MediaQuery.viewPaddingOf(context).bottom; + final double maxHeight = OnboardingBottomHills.height(context); + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + + return Positioned( + top: null, + bottom: 0.0, + left: 0.0, + right: 0.0, + height: maxHeight, + child: SizedBox( + child: Stack( + children: [ + Positioned.directional( + start: 0.0, + bottom: 0.0, + textDirection: textDirection, + child: SvgPicture.asset( + 'assets/onboarding/hill_start.svg', + height: maxHeight, + ), + ), + Positioned.directional( + end: 0.0, + bottom: 0.0, + textDirection: textDirection, + child: SvgPicture.asset( + 'assets/onboarding/hill_end.svg', + height: maxHeight * 0.965, + ), + ), + Positioned.directional( + textDirection: textDirection, + bottom: bottomPadding + (Platform.isIOS ? 0.0 : 15.0), + end: 15.0, + child: TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all( + Colors.white, + ), + padding: MaterialStateProperty.all( + const EdgeInsetsDirectional.only( + start: LARGE_SPACE + 1.0, + end: LARGE_SPACE, + top: SMALL_SPACE, + bottom: SMALL_SPACE, + ), + ), + elevation: MaterialStateProperty.all(4.0), + iconColor: MaterialStateProperty.all( + colors.orange, + ), + foregroundColor: MaterialStateProperty.all( + colors.orange, + ), + iconSize: MaterialStateProperty.all(21.0), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + ), + shadowColor: MaterialStateProperty.all( + Colors.black.withOpacity(0.50), + ), + ), + onPressed: onTap, + child: Row( + children: [ + Text( + AppLocalizations.of(context).onboarding_continue_button, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 22.0, + ), + ), + const SizedBox(width: LARGE_SPACE), + const icons.Arrow.right(), + ], + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/packages/smooth_app/lib/widgets/smooth_text.dart b/packages/smooth_app/lib/widgets/smooth_text.dart index c8a3b9c5ef6..bfa2f17066c 100644 --- a/packages/smooth_app/lib/widgets/smooth_text.dart +++ b/packages/smooth_app/lib/widgets/smooth_text.dart @@ -190,3 +190,31 @@ class TextHighlighter extends StatelessWidget { return endPosition + diff; } } + +class HighlightedTextSpan extends WidgetSpan { + HighlightedTextSpan({ + required String text, + required TextStyle textStyle, + required EdgeInsetsGeometry padding, + required Color backgroundColor, + required double radius, + EdgeInsetsGeometry? margin, + }) : assert(radius > 0.0), + super( + alignment: PlaceholderAlignment.middle, + child: Container( + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: BorderRadius.all( + Radius.circular(radius), + ), + ), + margin: margin, + padding: padding, + child: Text( + text, + style: textStyle, + ), + ), + ); +} From 621184c28caa8ab97efdfa34c43738c2d1673d6a Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 15 Jun 2024 18:07:18 +0200 Subject: [PATCH 13/85] chore: A better name for NutriScore v2 guide in the FAQ (#5380) * A better name for NutriScore v2 guide in the FAQ * Hide the icon * Update packages/smooth_app/lib/l10n/app_en.arb --------- Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_en.arb | 1 + .../lib/pages/preferences/user_preferences_faq.dart | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 7cc4f69934a..884cc740c29 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -2665,6 +2665,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart index 4f95d18e362..53a523f6999 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart @@ -66,7 +66,7 @@ class UserPreferencesFaq extends AbstractUserPreferences { ), ), _getListTile( - title: appLocalizations.nutriscore_generic, + title: appLocalizations.faq_nutriscore_nutriscore, leadingSvg: SvgCache.getAssetsCacheForNutriscore( NutriScoreValue.b, true, @@ -76,6 +76,12 @@ class UserPreferencesFaq extends AbstractUserPreferences { builder: (BuildContext context) => const GuideNutriscoreV2(), ), ), + + /// Hide the icon + icon: const Icon( + Icons.info, + size: 0.0, + ), ), _getNutriListTile( title: appLocalizations.ecoscore_generic, From 9f7d9d42c075f351b458dbb145b2dccb7717f7e6 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 15 Jun 2024 18:07:31 +0200 Subject: [PATCH 14/85] Add the Ristreto color to the palette (#5379) --- .../lib/themes/smooth_theme_colors.dart | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/smooth_app/lib/themes/smooth_theme_colors.dart b/packages/smooth_app/lib/themes/smooth_theme_colors.dart index 3c171810565..76637bd70e0 100644 --- a/packages/smooth_app/lib/themes/smooth_theme_colors.dart +++ b/packages/smooth_app/lib/themes/smooth_theme_colors.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; class SmoothColorsThemeExtension extends ThemeExtension { SmoothColorsThemeExtension({ + required this.primaryUltraBlack, required this.primaryBlack, required this.primaryDark, required this.primarySemiDark, @@ -19,7 +20,8 @@ class SmoothColorsThemeExtension }); SmoothColorsThemeExtension.defaultValues() - : primaryBlack = const Color(0xFF341100), + : primaryUltraBlack = const Color(0xFF52443D), + primaryBlack = const Color(0xFF341100), primaryDark = const Color(0xFF483527), primarySemiDark = const Color(0xFF52443D), primaryNormal = const Color(0xFFA08D84), @@ -33,11 +35,19 @@ class SmoothColorsThemeExtension greyDark = const Color(0xFF666666), greyLight = const Color(0xFF8F8F8F); + // Ristreto + final Color primaryUltraBlack; + // Chocolate final Color primaryBlack; + // Cortado final Color primaryDark; + // Mocha final Color primarySemiDark; + // Macchiato final Color primaryNormal; + // Cappuccino final Color primaryMedium; + // Latte final Color primaryLight; final Color secondaryNormal; final Color secondaryLight; @@ -49,6 +59,7 @@ class SmoothColorsThemeExtension @override ThemeExtension copyWith({ + Color? primaryUltraBlack, Color? primaryBlack, Color? primaryDark, Color? primarySemiDark, @@ -64,6 +75,7 @@ class SmoothColorsThemeExtension Color? greyLight, }) { return SmoothColorsThemeExtension( + primaryUltraBlack: primaryUltraBlack ?? this.primaryUltraBlack, primaryBlack: primaryBlack ?? this.primaryBlack, primaryDark: primaryDark ?? this.primaryDark, primarySemiDark: primarySemiDark ?? this.primarySemiDark, @@ -90,6 +102,11 @@ class SmoothColorsThemeExtension } return SmoothColorsThemeExtension( + primaryUltraBlack: Color.lerp( + primaryUltraBlack, + other.primaryUltraBlack, + t, + )!, primaryBlack: Color.lerp( primaryBlack, other.primaryBlack, From 780985462a773ca63fd7db8ed101541347fd3441 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Sun, 16 Jun 2024 09:14:25 +0200 Subject: [PATCH 15/85] feat: prices - top contributors now within the app (#5383) * feat: prices - top contributors now locally New files: * `price_user_button.dart`: Widget that displays a user, for Prices. * `prices_users_page.dart`: Page that displays the top prices users. Impacted files: * `app_en.arb`: added 2 label for "Contributor prices" * `app_fr.arb`: added 2 label for "Contributor prices" * `price_count_widget.dart`: minor refactoring * `price_data_widget.dart`: minor refactoring using new class `PriceUserButton` * `user_preferences_account.dart`: local display of top users; minor refactoring using new class `PriceUserButton` * Added comment. --- packages/smooth_app/lib/l10n/app_en.arb | 16 ++ packages/smooth_app/lib/l10n/app_fr.arb | 16 ++ .../preferences/user_preferences_account.dart | 44 ++---- .../lib/pages/prices/price_count_widget.dart | 14 +- .../lib/pages/prices/price_data_widget.dart | 9 +- .../lib/pages/prices/price_user_button.dart | 63 ++++++++ .../lib/pages/prices/prices_users_page.dart | 143 ++++++++++++++++++ 7 files changed, 264 insertions(+), 41 deletions(-) create mode 100644 packages/smooth_app/lib/pages/prices/price_user_button.dart create mode 100644 packages/smooth_app/lib/pages/prices/prices_users_page.dart diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 884cc740c29..50390b78bd9 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1709,6 +1709,18 @@ } } }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", @@ -1801,6 +1813,10 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 1b8811a31c8..e6a2fbb625d 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1711,6 +1711,18 @@ } } }, + "prices_users_list_length_many_pages": "Top {pageSize} contributeurs (total : {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Montant", "prices_amount_is_discounted": "En promotion ?", "prices_amount_price_normal": "Prix", @@ -1798,6 +1810,10 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_any_search_prices_title": "Prix d'un contributeur", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Derniers prix ajoutés", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart index a8b3e6499b7..63d179ddd82 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart @@ -18,7 +18,9 @@ import 'package:smooth_app/pages/preferences/user_preferences_item.dart'; import 'package:smooth_app/pages/preferences/user_preferences_list_tile.dart'; import 'package:smooth_app/pages/preferences/user_preferences_page.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; +import 'package:smooth_app/pages/prices/price_user_button.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; +import 'package:smooth_app/pages/prices/prices_users_page.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/pages/user_management/login_page.dart'; import 'package:smooth_app/query/paged_product_query.dart'; @@ -214,32 +216,13 @@ class UserPreferencesAccount extends AbstractUserPreferences { myCount: _getMyCount(UserSearchType.TO_BE_COMPLETED), ), _getListTile( - appLocalizations.user_search_prices_title, - () async => Navigator.of(context).push( - MaterialPageRoute( - builder: (BuildContext context) => PricesPage( - GetPricesModel( - parameters: GetPricesParameters() - ..owner = userId - ..orderBy = >[ - const OrderBy( - field: GetPricesOrderField.created, - ascending: false, - ), - ] - ..pageSize = GetPricesModel.pageSize - ..pageNumber = 1, - displayOwner: false, - displayProduct: true, - uri: OpenPricesAPIClient.getUri( - path: 'app/users/${ProductQuery.getWriteUser().userId}', - uriHelper: ProductQuery.uriProductHelper, - ), - title: appLocalizations.user_search_prices_title, - subtitle: ProductQuery.getWriteUser().userId, - ), - ), - ), + PriceUserButton.showUserTitle( + user: ProductQuery.getWriteUser().userId, + context: context, + ), + () async => PriceUserButton.showUserPrices( + user: ProductQuery.getWriteUser().userId, + context: context, ), CupertinoIcons.money_dollar_circle, myCount: _getPricesCount(owner: ProductQuery.getWriteUser().userId), @@ -273,9 +256,14 @@ class UserPreferencesAccount extends AbstractUserPreferences { CupertinoIcons.money_dollar_circle, myCount: _getPricesCount(), ), - _getPriceListTile( + _getListTile( appLocalizations.all_search_prices_top_user_title, - 'app/users', + () async => Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => const PricesUsersPage(), + ), + ), + Icons.account_box, ), _getPriceListTile( appLocalizations.all_search_prices_top_location_title, diff --git a/packages/smooth_app/lib/pages/prices/price_count_widget.dart b/packages/smooth_app/lib/pages/prices/price_count_widget.dart index a1604d978e5..0b1fa92a402 100644 --- a/packages/smooth_app/lib/pages/prices/price_count_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_count_widget.dart @@ -49,21 +49,23 @@ class PriceCountWidget extends StatelessWidget { title: '$count', buttonStyle: ElevatedButton.styleFrom( disabledForegroundColor: - enableCountButton ? null : _getForegroundColor(), + enableCountButton ? null : getForegroundColor(count), disabledBackgroundColor: - enableCountButton ? null : _getBackgroundColor(), - foregroundColor: !enableCountButton ? null : _getForegroundColor(), - backgroundColor: !enableCountButton ? null : _getBackgroundColor(), + enableCountButton ? null : getBackgroundColor(count), + foregroundColor: + !enableCountButton ? null : getForegroundColor(count), + backgroundColor: + !enableCountButton ? null : getBackgroundColor(count), ), ); - Color? _getForegroundColor() => switch (count) { + static Color? getForegroundColor(final int count) => switch (count) { 0 => Colors.red, 1 => Colors.orange, _ => Colors.green, }; - Color? _getBackgroundColor() => switch (count) { + static Color? getBackgroundColor(final int count) => switch (count) { 0 => Colors.red[100], 1 => Colors.orange[100], _ => Colors.green[100], diff --git a/packages/smooth_app/lib/pages/prices/price_data_widget.dart b/packages/smooth_app/lib/pages/prices/price_data_widget.dart index cf2bf4cdefd..c16daeece66 100644 --- a/packages/smooth_app/lib/pages/prices/price_data_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_data_widget.dart @@ -7,6 +7,7 @@ import 'package:smooth_app/helpers/launch_url_helper.dart'; import 'package:smooth_app/pages/prices/emoji_helper.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/price_button.dart'; +import 'package:smooth_app/pages/prices/price_user_button.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/query/product_query.dart'; @@ -79,13 +80,7 @@ class PriceDataWidget extends StatelessWidget { iconData: Icons.location_on_outlined, onPressed: () {}, ), - if (model.displayOwner) - PriceButton( - // TODO(monsieurtanuki): open a still-to-be-done "price x owner" page - title: price.owner, - iconData: Icons.account_box, - onPressed: () {}, - ), + if (model.displayOwner) PriceUserButton(price.owner), Tooltip( message: '${dateFormat.format(price.created)}' ' ' diff --git a/packages/smooth_app/lib/pages/prices/price_user_button.dart b/packages/smooth_app/lib/pages/prices/price_user_button.dart new file mode 100644 index 00000000000..6d8e86b8229 --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_user_button.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/pages/prices/get_prices_model.dart'; +import 'package:smooth_app/pages/prices/price_button.dart'; +import 'package:smooth_app/pages/prices/prices_page.dart'; +import 'package:smooth_app/query/product_query.dart'; + +/// Widget that displays a user, for Prices. +class PriceUserButton extends StatelessWidget { + const PriceUserButton(this.user); + + final String user; + + static String showUserTitle({ + required final String user, + required final BuildContext context, + }) => + user == ProductQuery.getWriteUser().userId + ? AppLocalizations.of(context).user_search_prices_title + : AppLocalizations.of(context).user_any_search_prices_title; + + static Future showUserPrices({ + required final String user, + required final BuildContext context, + }) async => + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => PricesPage( + GetPricesModel( + parameters: GetPricesParameters() + ..owner = user + ..orderBy = >[ + const OrderBy( + field: GetPricesOrderField.created, + ascending: false, + ), + ] + ..pageSize = GetPricesModel.pageSize + ..pageNumber = 1, + displayOwner: false, + displayProduct: true, + uri: OpenPricesAPIClient.getUri( + path: 'app/users/$user', + uriHelper: ProductQuery.uriProductHelper, + ), + title: showUserTitle(user: user, context: context), + subtitle: user, + ), + ), + ), + ); + + @override + Widget build(BuildContext context) => PriceButton( + title: user, + iconData: Icons.account_box, + onPressed: () async => showUserPrices( + user: user, + context: context, + ), + ); +} diff --git a/packages/smooth_app/lib/pages/prices/prices_users_page.dart b/packages/smooth_app/lib/pages/prices/prices_users_page.dart new file mode 100644 index 00000000000..07a32bbe50f --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/prices_users_page.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; +import 'package:smooth_app/helpers/launch_url_helper.dart'; +import 'package:smooth_app/pages/prices/price_button.dart'; +import 'package:smooth_app/pages/prices/price_count_widget.dart'; +import 'package:smooth_app/pages/prices/price_user_button.dart'; +import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Page that displays the top prices users. +class PricesUsersPage extends StatefulWidget { + const PricesUsersPage(); + + @override + State createState() => _PricesUsersPageState(); +} + +class _PricesUsersPageState extends State { + late final Future> _users = _showTopUsers(); + + // In this specific page, let's never try to go beyond the top 10. + // cf. https://github.com/openfoodfacts/smooth-app/pull/5383#issuecomment-2171117141 + static const int _pageSize = 10; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + return SmoothScaffold( + appBar: SmoothAppBar( + centerTitle: false, + leading: const SmoothBackButton(), + title: Text( + appLocalizations.all_search_prices_top_user_title, + ), + actions: [ + IconButton( + tooltip: appLocalizations.prices_app_button, + icon: const Icon(Icons.open_in_new), + onPressed: () async => LaunchUrlHelper.launchURL( + OpenPricesAPIClient.getUri( + path: 'app/users', + uriHelper: ProductQuery.uriProductHelper, + ).toString(), + ), + ), + ], + ), + body: FutureBuilder>( + future: _users, + builder: ( + final BuildContext context, + final AsyncSnapshot> snapshot, + ) { + if (snapshot.connectionState != ConnectionState.done) { + return const CircularProgressIndicator(); + } + if (snapshot.hasError) { + return Text(snapshot.error!.toString()); + } + // highly improbable + if (!snapshot.hasData) { + return const Text('no data'); + } + if (snapshot.data!.isError) { + return Text(snapshot.data!.error!); + } + final GetUsersResult result = snapshot.data!.value; + // highly improbable + if (result.items == null) { + return const Text('empty list'); + } + final List children = []; + + for (final PriceUser item in result.items!) { + children.add( + SmoothCard( + child: Wrap( + spacing: VERY_SMALL_SPACE, + children: [ + PriceUserButton(item.userId), + PriceButton( + onPressed: () async => PriceUserButton.showUserPrices( + user: item.userId, + context: context, + ), + iconData: Icons.label, + title: '${item.priceCount}', + buttonStyle: ElevatedButton.styleFrom( + foregroundColor: PriceCountWidget.getForegroundColor( + item.priceCount, + ), + backgroundColor: PriceCountWidget.getBackgroundColor( + item.priceCount, + ), + ), + ), + ], + ), + ), + ); + } + final AppLocalizations appLocalizations = + AppLocalizations.of(context); + final String title = + appLocalizations.prices_users_list_length_many_pages( + _pageSize, + result.total!, + ); + children.insert( + 0, + SmoothCard(child: ListTile(title: Text(title))), + ); + // so that the last content gets not hidden by the FAB + children.add( + const SizedBox(height: 2 * MINIMUM_TOUCH_SIZE), + ); + return ListView( + children: children, + ); + }, + ), + ); + } + + static Future> _showTopUsers() async => + OpenPricesAPIClient.getUsers( + GetUsersParameters() + ..orderBy = >[ + const OrderBy( + field: GetUsersOrderField.priceCount, + ascending: false, + ), + ] + ..pageSize = _pageSize + ..pageNumber = 1, + uriHelper: ProductQuery.uriProductHelper, + ); +} From 4fbf0203acb366f6d797b20a4b22f3a2c3a89523 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Sun, 16 Jun 2024 14:08:45 +0200 Subject: [PATCH 16/85] feat: 5207 - new "My proofs" and "Proof" pages (#5389) * feat: 5207 - new "My proofs" and "Proof" pages New files: * `price_proof_page.dart`: Full page display of a proof. * `prices_proofs_page.dart`: Page that displays the latest proofs of the current user. Impacted files: * `app_en.arb`: added 3 labels for "my proofs" * `app_fr.arb`: added 3 labels for "my proofs" * `price_data_widget.dart`: instead of a web app link, we open the new "my proof" page * `user_preferences_account.dart`: added a link to open the new "my proofs" page * Minor rewording. --- packages/smooth_app/lib/l10n/app_en.arb | 29 +++ packages/smooth_app/lib/l10n/app_fr.arb | 29 +++ .../preferences/user_preferences_account.dart | 10 + .../lib/pages/prices/price_data_widget.dart | 17 +- .../lib/pages/prices/price_proof_page.dart | 45 ++++ .../lib/pages/prices/prices_proofs_page.dart | 233 ++++++++++++++++++ 6 files changed, 355 insertions(+), 8 deletions(-) create mode 100644 packages/smooth_app/lib/pages/prices/price_proof_page.dart create mode 100644 packages/smooth_app/lib/pages/prices/prices_proofs_page.dart diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 50390b78bd9..4bf432693ef 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1709,6 +1709,27 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", "@prices_users_list_length_many_pages": { "description": "Number of users for one-page result", @@ -1813,6 +1834,14 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, "user_any_search_prices_title": "Contributor prices", "@user_any_search_prices_title": { "description": "User prices (everybody except me): list tile title" diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index e6a2fbb625d..81c01ace21f 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1711,6 +1711,27 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{Aucune preuve} =1{Une seule preuve} other{Toutes les {count} preuves}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "{pageSize} preuves les plus récentes (total : {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_users_list_length_many_pages": "Top {pageSize} contributeurs (total : {total})", "@prices_users_list_length_many_pages": { "description": "Number of users for one-page result", @@ -1810,6 +1831,14 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Mes preuves", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "Ma preuve", + "@user_search_proof_title": { + "description": "User proof: page title" + }, "user_any_search_prices_title": "Prix d'un contributeur", "@user_any_search_prices_title": { "description": "User prices (everybody except me): list tile title" diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart index 63d179ddd82..8104857b724 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart @@ -20,6 +20,7 @@ import 'package:smooth_app/pages/preferences/user_preferences_page.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/price_user_button.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; +import 'package:smooth_app/pages/prices/prices_proofs_page.dart'; import 'package:smooth_app/pages/prices/prices_users_page.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/pages/user_management/login_page.dart'; @@ -227,6 +228,15 @@ class UserPreferencesAccount extends AbstractUserPreferences { CupertinoIcons.money_dollar_circle, myCount: _getPricesCount(owner: ProductQuery.getWriteUser().userId), ), + _getListTile( + appLocalizations.user_search_proofs_title, + () async => Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => const PricesProofsPage(), + ), + ), + Icons.receipt, + ), _getListTile( appLocalizations.all_search_prices_latest_title, () async => Navigator.of(context).push( diff --git a/packages/smooth_app/lib/pages/prices/price_data_widget.dart b/packages/smooth_app/lib/pages/prices/price_data_widget.dart index c16daeece66..142f6d7c1e3 100644 --- a/packages/smooth_app/lib/pages/prices/price_data_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_data_widget.dart @@ -3,10 +3,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/helpers/launch_url_helper.dart'; import 'package:smooth_app/pages/prices/emoji_helper.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/price_button.dart'; +import 'package:smooth_app/pages/prices/price_proof_page.dart'; import 'package:smooth_app/pages/prices/price_user_button.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/query/product_query.dart'; @@ -99,13 +99,14 @@ class PriceDataWidget extends StatelessWidget { if (price.proof?.filePath != null) PriceButton( iconData: Icons.image, - onPressed: () async => LaunchUrlHelper.launchURL( - price.proof! - .getFileUrl( - uriProductHelper: ProductQuery.uriProductHelper, - ) - .toString(), - ), + onPressed: () async => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => PriceProofPage( + price.proof!, + ), + ), + ), // PriceProofPage ), ], ); diff --git a/packages/smooth_app/lib/pages/prices/price_proof_page.dart b/packages/smooth_app/lib/pages/prices/price_proof_page.dart new file mode 100644 index 00000000000..d0ddf0eabdf --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/price_proof_page.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:intl/intl.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/helpers/launch_url_helper.dart'; +import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Full page display of a proof. +class PriceProofPage extends StatelessWidget { + const PriceProofPage( + this.proof, + ); + + final Proof proof; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final DateFormat dateFormat = + DateFormat.yMd(ProductQuery.getLocaleString()).add_Hms(); + return SmoothScaffold( + appBar: SmoothAppBar( + title: Text(appLocalizations.user_search_proof_title), + subTitle: Text(dateFormat.format(proof.created)), + actions: [ + IconButton( + tooltip: appLocalizations.prices_app_button, + icon: const Icon(Icons.open_in_new), + onPressed: () async => LaunchUrlHelper.launchURL(_getUrl()), + ), + ], + ), + body: Image( + image: NetworkImage(_getUrl()), + fit: BoxFit.cover, + ), + ); + } + + String _getUrl() => proof + .getFileUrl(uriProductHelper: ProductQuery.uriProductHelper) + .toString(); +} diff --git a/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart b/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart new file mode 100644 index 00000000000..fe5f202231c --- /dev/null +++ b/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart @@ -0,0 +1,233 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:intl/intl.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; +import 'package:smooth_app/helpers/launch_url_helper.dart'; +import 'package:smooth_app/pages/prices/price_proof_page.dart'; +import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; + +/// Page that displays the latest proofs of the current user. +class PricesProofsPage extends StatefulWidget { + const PricesProofsPage(); + + @override + State createState() => _PricesProofsPageState(); +} + +class _PricesProofsPageState extends State { + late final Future> _results = _download(); + + static const int _columns = 3; + static const int _rows = 5; + static const int _pageSize = _columns * _rows; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + return SmoothScaffold( + appBar: SmoothAppBar( + centerTitle: false, + leading: const SmoothBackButton(), + title: Text( + appLocalizations.user_search_proofs_title, + ), + actions: [ + IconButton( + tooltip: appLocalizations.prices_app_button, + icon: const Icon(Icons.open_in_new), + onPressed: () async => LaunchUrlHelper.launchURL( + OpenPricesAPIClient.getUri( + path: 'app/dashboard/proofs', + uriHelper: ProductQuery.uriProductHelper, + ).toString(), + ), + ), + ], + ), + body: FutureBuilder>( + future: _results, + builder: ( + final BuildContext context, + final AsyncSnapshot> snapshot, + ) { + if (snapshot.connectionState != ConnectionState.done) { + return const CircularProgressIndicator(); + } + if (snapshot.hasError) { + return Text(snapshot.error!.toString()); + } + // highly improbable + if (!snapshot.hasData) { + return const Text('no data'); + } + if (snapshot.data!.isError) { + return Text(snapshot.data!.error!); + } + final GetProofsResult result = snapshot.data!.value; + // highly improbable + if (result.items == null) { + return const Text('empty list'); + } + final double squareSize = MediaQuery.sizeOf(context).width / _columns; + + final AppLocalizations appLocalizations = + AppLocalizations.of(context); + final String title = result.numberOfPages == 1 + ? appLocalizations.prices_proofs_list_length_one_page( + result.items!.length, + ) + : appLocalizations.prices_proofs_list_length_many_pages( + _pageSize, + result.total!, + ); + return Column( + children: [ + SmoothCard( + child: ListTile( + title: Text(title), + ), + ), + if (result.items!.isNotEmpty) + Expanded( + child: CustomScrollView( + slivers: [ + SliverGrid( + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: _columns, + ), + delegate: SliverChildBuilderDelegate( + ( + final BuildContext context, + final int index, + ) { + final Proof proof = result.items![index]; + if (proof.filePath == null) { + // highly improbable + return SizedBox( + width: squareSize, + height: squareSize, + ); + } + return InkWell( + onTap: () async => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => + PriceProofPage( + proof, + ), + ), + ), // PriceProofPage + child: _PriceProofImage(proof, + squareSize: squareSize), + ); + }, + addAutomaticKeepAlives: false, + childCount: result.items!.length, + ), + ), + ], + ), + ), + ], + ); + }, + ), + ); + } + + static Future> _download() async { + final User user = ProductQuery.getWriteUser(); + final MaybeError token = + await OpenPricesAPIClient.getAuthenticationToken( + username: user.userId, + password: user.password, + uriHelper: ProductQuery.uriProductHelper, + ); + final String bearerToken = token.value; + + final MaybeError result = + await OpenPricesAPIClient.getProofs( + GetProofsParameters() + ..orderBy = >[ + const OrderBy( + field: GetProofsOrderField.created, + ascending: false, + ), + ] + ..pageSize = _pageSize + ..pageNumber = 1, + uriHelper: ProductQuery.uriProductHelper, + bearerToken: bearerToken, + ); + + await OpenPricesAPIClient.deleteUserSession( + uriHelper: ProductQuery.uriProductHelper, + bearerToken: bearerToken, + ); + + return result; + } +} + +// TODO(monsieurtanuki): reuse whatever will be coded in https://github.com/openfoodfacts/smooth-app/pull/5366 +class _PriceProofImage extends StatelessWidget { + const _PriceProofImage( + this.proof, { + required this.squareSize, + }); + + final Proof proof; + final double squareSize; + + @override + Widget build(BuildContext context) { + final DateFormat dateFormat = + DateFormat.yMd(ProductQuery.getLocaleString()); + final String date = dateFormat.format(proof.created); + return Stack( + children: [ + SmoothImage( + width: squareSize, + height: squareSize, + imageProvider: NetworkImage( + proof + .getFileUrl( + uriProductHelper: ProductQuery.uriProductHelper, + ) + .toString(), + ), + rounded: false, + ), + SizedBox( + width: squareSize, + height: squareSize, + child: Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(SMALL_SPACE), + child: Container( + height: VERY_LARGE_SPACE, + color: Colors.white.withAlpha(128), + child: Center( + child: AutoSizeText( + date, + maxLines: 1, + ), + ), + ), + ), + ), + ), + ], + ); + } +} From a3e9bc24ec38ce0301492061c95c78446cf830e7 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sun, 16 Jun 2024 17:39:33 +0200 Subject: [PATCH 17/85] refactor: Rename `tagline*` to `AppNews` (#5377) * Rename `tagline*` to `AppNews` * Fix labeler path --- .github/labeler.yml | 2 +- .../newsfeed_json.dart} | 37 +- .../newsfeed_model.dart} | 58 +-- .../newsfeed_provider.dart} | 88 ++-- .../knowledge_panel_page.dart | 4 +- packages/smooth_app/lib/main.dart | 6 +- .../lib/pages/navigator/app_navigator.dart | 10 +- .../onboarding/onboarding_flow_navigator.dart | 4 +- .../smooth_app/lib/pages/page_manager.dart | 6 +- .../user_preferences_language_selector.dart | 6 +- .../product/common/product_list_page.dart | 4 +- .../lib/pages/product/new_product_page.dart | 6 +- .../carousel/main_card/scan_main_card.dart | 179 +++++++++ .../main_card}/scan_tagline.dart | 60 +-- .../pages/scan/carousel/scan_carousel.dart | 195 +++++++++ .../carousel/scan_carousel_manager.dart} | 22 +- .../smooth_app/lib/pages/scan/scan_page.dart | 5 +- .../lib/widgets/smooth_product_carousel.dart | 375 ------------------ 18 files changed, 533 insertions(+), 534 deletions(-) rename packages/smooth_app/lib/data_models/{tagline/tagline_json.dart => news_feed/newsfeed_json.dart} (94%) rename packages/smooth_app/lib/data_models/{tagline/tagline_model.dart => news_feed/newsfeed_model.dart} (72%) rename packages/smooth_app/lib/data_models/{tagline/tagline_provider.dart => news_feed/newsfeed_provider.dart} (67%) create mode 100644 packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart rename packages/smooth_app/lib/pages/scan/{ => carousel/main_card}/scan_tagline.dart (87%) create mode 100644 packages/smooth_app/lib/pages/scan/carousel/scan_carousel.dart rename packages/smooth_app/lib/pages/{carousel_manager.dart => scan/carousel/scan_carousel_manager.dart} (75%) delete mode 100644 packages/smooth_app/lib/widgets/smooth_product_carousel.dart diff --git a/.github/labeler.yml b/.github/labeler.yml index 8aa4e9d1757..be330d5dbcc 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -240,7 +240,7 @@ User lists: Product scan carousel: - changed-files: - - any-glob-to-any-file: 'packages/smooth_app/lib/widgets/smooth_product_carousel.dart' + - any-glob-to-any-file: 'packages/smooth_app/lib/pages/scan/carousel/scan_carousel.dart' ✏️ Editing - 📦 Packaging input: - changed-files: diff --git a/packages/smooth_app/lib/data_models/tagline/tagline_json.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart similarity index 94% rename from packages/smooth_app/lib/data_models/tagline/tagline_json.dart rename to packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart index 4fced2ae96f..9ddd6e2a7ab 100644 --- a/packages/smooth_app/lib/data_models/tagline/tagline_json.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart @@ -1,6 +1,6 @@ -part of 'tagline_provider.dart'; +part of 'newsfeed_provider.dart'; -/// Content from the JSON and converted to what's in "tagmodel.dart" +/// Content from the JSON and converted to what's in "newsfeed_model.dart" class _TagLineJSON { _TagLineJSON.fromJson(Map json) @@ -15,17 +15,16 @@ class _TagLineJSON { final _TagLineJSONNewsList news; final _TaglineJSONFeed taglineFeed; - TagLine toTagLine(String locale) { - final Map tagLineNews = news.map( - (String key, _TagLineItemNewsItem value) => - MapEntry( + AppNews toTagLine(String locale) { + final Map tagLineNews = news.map( + (String key, _TagLineItemNewsItem value) => MapEntry( key, value.toTagLineItem(locale), ), ); final _TagLineJSONFeedLocale localizedFeed = taglineFeed.loadNews(locale); - final Iterable feed = localizedFeed.news + final Iterable feed = localizedFeed.news .map((_TagLineJSONFeedLocaleItem item) { if (news[item.id] == null) { // The asked ID doesn't exist in the news @@ -33,16 +32,16 @@ class _TagLineJSON { } return item.overrideNewsItem(news[item.id]!, locale); }) - .where((TagLineFeedItem? item) => + .where((AppNewsFeedItem? item) => item != null && (item.startDate == null || item.startDate!.isBefore(DateTime.now())) && (item.endDate == null || item.endDate!.isAfter(DateTime.now()))) .whereNotNull(); - return TagLine( - news: TagLineNewsList(tagLineNews), - feed: TagLineFeed( + return AppNews( + news: AppNewsList(tagLineNews), + feed: AppNewsFeed( feed.toList(growable: false), ), ); @@ -106,10 +105,10 @@ class _TagLineItemNewsItem { return _translations['default']!.merge(translation); } - TagLineNewsItem toTagLineItem(String locale) { + AppNewsItem toTagLineItem(String locale) { final _TagLineItemNewsTranslation translation = loadTranslation(locale); // We can assume the default translation has a non-null title and message - return TagLineNewsItem( + return AppNewsItem( id: id, title: translation.title!, message: translation.message!, @@ -224,8 +223,8 @@ class _TagLineNewsImage { final double? width; final String? alt; - TagLineImage toTagLineImage() { - return TagLineImage( + AppNewsImage toTagLineImage() { + return AppNewsImage( src: url, width: width, alt: alt, @@ -303,7 +302,7 @@ class _TagLineNewsStyle { ); } - TagLineStyle toTagLineStyle() => TagLineStyle.fromHexa( + AppNewsStyle toTagLineStyle() => AppNewsStyle.fromHexa( titleBackground: titleBackground, titleTextColor: titleTextColor, titleIndicatorColor: titleIndicatorColor, @@ -369,7 +368,7 @@ class _TagLineJSONFeedLocaleItem { final String id; final _TagLineJSONFeedNewsItemOverride? overrideContent; - TagLineFeedItem overrideNewsItem( + AppNewsFeedItem overrideNewsItem( _TagLineItemNewsItem newsItem, String locale, ) { @@ -384,9 +383,9 @@ class _TagLineJSONFeedLocaleItem { ); } - final TagLineNewsItem tagLineItem = item.toTagLineItem(locale); + final AppNewsItem tagLineItem = item.toTagLineItem(locale); - return TagLineFeedItem( + return AppNewsFeedItem( news: tagLineItem, startDate: tagLineItem.startDate, endDate: tagLineItem.endDate, diff --git a/packages/smooth_app/lib/data_models/tagline/tagline_model.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart similarity index 72% rename from packages/smooth_app/lib/data_models/tagline/tagline_model.dart rename to packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart index 20698d5713d..59226e46cab 100644 --- a/packages/smooth_app/lib/data_models/tagline/tagline_model.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart @@ -1,35 +1,35 @@ import 'dart:ui'; -class TagLine { - const TagLine({ +class AppNews { + const AppNews({ required this.news, required this.feed, }); - final TagLineNewsList news; - final TagLineFeed feed; + final AppNewsList news; + final AppNewsFeed feed; @override String toString() { - return 'TagLine{news: $news, feed: $feed}'; + return 'AppNews{news: $news, feed: $feed}'; } } -class TagLineNewsList { - const TagLineNewsList(Map news) : _news = news; +class AppNewsList { + const AppNewsList(Map news) : _news = news; - final Map _news; + final Map _news; - TagLineNewsItem? operator [](String key) => _news[key]; + AppNewsItem? operator [](String key) => _news[key]; @override String toString() { - return 'TagLineNewsList{_news: $_news}'; + return 'AppNewsList{_news: $_news}'; } } -class TagLineNewsItem { - const TagLineNewsItem({ +class AppNewsItem { + const AppNewsItem({ required this.id, required this.title, required this.message, @@ -48,17 +48,17 @@ class TagLineNewsItem { final String? buttonLabel; final DateTime? startDate; final DateTime? endDate; - final TagLineImage? image; - final TagLineStyle? style; + final AppNewsImage? image; + final AppNewsStyle? style; @override String toString() { - return 'TagLineNewsItem{id: $id, title: $title, message: $message, url: $url, buttonLabel: $buttonLabel, startDate: $startDate, endDate: $endDate, image: $image, style: $style}'; + return 'AppNewsItem{id: $id, title: $title, message: $message, url: $url, buttonLabel: $buttonLabel, startDate: $startDate, endDate: $endDate, image: $image, style: $style}'; } } -class TagLineStyle { - const TagLineStyle({ +class AppNewsStyle { + const AppNewsStyle({ this.titleBackground, this.titleTextColor, this.titleIndicatorColor, @@ -69,7 +69,7 @@ class TagLineStyle { this.contentBackgroundColor, }); - TagLineStyle.fromHexa({ + AppNewsStyle.fromHexa({ String? titleBackground, String? titleTextColor, String? titleIndicatorColor, @@ -105,12 +105,12 @@ class TagLineStyle { @override String toString() { - return 'TagLineStyle{titleBackground: $titleBackground, titleTextColor: $titleTextColor, titleIndicatorColor: $titleIndicatorColor, messageBackground: $messageBackground, messageTextColor: $messageTextColor, buttonBackground: $buttonBackground, buttonTextColor: $buttonTextColor, contentBackgroundColor: $contentBackgroundColor}'; + return 'AppNewsStyle{titleBackground: $titleBackground, titleTextColor: $titleTextColor, titleIndicatorColor: $titleIndicatorColor, messageBackground: $messageBackground, messageTextColor: $messageTextColor, buttonBackground: $buttonBackground, buttonTextColor: $buttonTextColor, contentBackgroundColor: $contentBackgroundColor}'; } } -class TagLineImage { - const TagLineImage({ +class AppNewsImage { + const AppNewsImage({ required this.src, this.width, this.alt, @@ -122,14 +122,14 @@ class TagLineImage { @override String toString() { - return 'TagLineImage{src: $src, width: $width, alt: $alt}'; + return 'AppNewsImage{src: $src, width: $width, alt: $alt}'; } } -class TagLineFeed { - const TagLineFeed(this.news); +class AppNewsFeed { + const AppNewsFeed(this.news); - final List news; + final List news; bool get isNotEmpty => news.isNotEmpty; @@ -139,15 +139,15 @@ class TagLineFeed { } } -class TagLineFeedItem { - const TagLineFeedItem({ +class AppNewsFeedItem { + const AppNewsFeedItem({ required this.news, DateTime? startDate, DateTime? endDate, }) : _startDate = startDate, _endDate = endDate; - final TagLineNewsItem news; + final AppNewsItem news; final DateTime? _startDate; final DateTime? _endDate; @@ -159,6 +159,6 @@ class TagLineFeedItem { @override String toString() { - return 'TagLineFeedItem{news: $news, _startDate: $_startDate, _endDate: $_endDate}'; + return 'AppNewsFeedItem{news: $news, _startDate: $_startDate, _endDate: $_endDate}'; } } diff --git a/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart similarity index 67% rename from packages/smooth_app/lib/data_models/tagline/tagline_provider.dart rename to packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart index 6489cb8ab54..f5b8e8619ab 100644 --- a/packages/smooth_app/lib/data_models/tagline/tagline_provider.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart @@ -8,23 +8,23 @@ import 'package:http/http.dart' as http; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_model.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; -import 'package:smooth_app/data_models/tagline/tagline_model.dart'; import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/query/product_query.dart'; import 'package:smooth_app/services/smooth_services.dart'; -part 'tagline_json.dart'; +part 'newsfeed_json.dart'; -/// The TagLine provides one one side a list of news and on the other a feed -/// containing the some of the news +/// This provides one one side a list of news and on the other a feed of news. +/// A feed contains some of the news? /// -/// The TagLine is fetched on the server and cached locally (1 day). +/// The content is fetched on the server and cached locally (1 day). /// To be notified of changes, listen to this [ChangeNotifier] and more -/// particularly to the [state] property -class TagLineProvider extends ChangeNotifier { - TagLineProvider(UserPreferences preferences) - : _state = const TagLineLoading(), +/// particularly to the [state] property. +class AppNewsProvider extends ChangeNotifier { + AppNewsProvider(UserPreferences preferences) + : _state = const AppNewsStateLoading(), _preferences = preferences, _domain = preferences.getDevModeString( UserPreferencesDevMode.userPreferencesTestEnvDomain) ?? @@ -33,17 +33,17 @@ class TagLineProvider extends ChangeNotifier { .getFlag(UserPreferencesDevMode.userPreferencesFlagProd) ?? true { _preferences.addListener(_onPreferencesChanged); - loadTagLine(); + loadLatestNews(); } final UserPreferences _preferences; - TagLineState _state; + AppNewsState _state; - bool get hasContent => _state is TagLineLoaded; + bool get hasContent => _state is AppNewsStateLoaded; - Future loadTagLine({bool forceUpdate = false}) async { - _emit(const TagLineLoading()); + Future loadLatestNews({bool forceUpdate = false}) async { + _emit(const AppNewsStateLoading()); final String locale = ProductQuery.getLocaleString(); if (locale.startsWith('-')) { @@ -51,43 +51,43 @@ class TagLineProvider extends ChangeNotifier { return; } - final File cacheFile = await _tagLineCacheFile; + final File cacheFile = await _newsCacheFile; String? jsonString; // Try from the cache first - if (!forceUpdate && _isTagLineCacheValid(cacheFile)) { + if (!forceUpdate && _isNewsCacheValid(cacheFile)) { jsonString = cacheFile.readAsStringSync(); } if (jsonString == null || jsonString.isEmpty == true) { - jsonString = await _fetchTagLine(); + jsonString = await _fetchJSON(); } if (jsonString?.isNotEmpty != true) { - _emit(const TagLineError('JSON file is empty')); + _emit(const AppNewsStateError('JSON news file is empty')); return; } - final TagLine? tagLine = await Isolate.run( + final AppNews? tagLine = await Isolate.run( () => _parseJSONAndGetLocalizedContent(jsonString!, locale)); if (tagLine == null) { - _emit(const TagLineError('Unable to parse the JSON file')); - Logs.e('Unable to parse the Tagline file'); + _emit(const AppNewsStateError('Unable to parse the JSON news file')); + Logs.e('Unable to parse the JSON news file'); } else { - _emit(TagLineLoaded(tagLine)); - Logs.i('TagLine reloaded'); + _emit(AppNewsStateLoaded(tagLine)); + Logs.i('News ${forceUpdate ? 're' : ''}loaded'); } } - void _emit(TagLineState state) { + void _emit(AppNewsState state) { _state = state; WidgetsBinding.instance.addPostFrameCallback((_) { notifyListeners(); }); } - TagLineState get state => _state; + AppNewsState get state => _state; - static Future _parseJSONAndGetLocalizedContent( + static Future _parseJSONAndGetLocalizedContent( String json, String locale, ) async { @@ -102,11 +102,11 @@ class TagLineProvider extends ChangeNotifier { /// API URL: [https://world.openfoodfacts.[org/net]/resources/files/tagline-off-ios-v3.json] /// or [https://world.openfoodfacts.[org/net]/resources/files/tagline-off-android-v3.json] - Future _fetchTagLine() async { + Future _fetchJSON() async { try { final UriProductHelper uriProductHelper = ProductQuery.uriProductHelper; final Map headers = {}; - final Uri uri = uriProductHelper.getUri(path: _tagLineUrl); + final Uri uri = uriProductHelper.getUri(path: _newsUrl); if (uriProductHelper.userInfoForPatch != null) { headers['Authorization'] = @@ -125,7 +125,7 @@ class TagLineProvider extends ChangeNotifier { if (!json.startsWith('[') && !json.startsWith('{')) { throw Exception('Invalid JSON'); } - await _saveTagLineToCache(json); + await _saveNewsToCache(json); return json; } catch (_) { return null; @@ -133,7 +133,7 @@ class TagLineProvider extends ChangeNotifier { } /// Based on the platform, the URL may differ - String get _tagLineUrl { + String get _newsUrl { if (Platform.isIOS || Platform.isMacOS) { return '/resources/files/tagline-off-ios-v3.json'; } else { @@ -141,15 +141,15 @@ class TagLineProvider extends ChangeNotifier { } } - Future get _tagLineCacheFile => getApplicationCacheDirectory() + Future get _newsCacheFile => getApplicationCacheDirectory() .then((Directory dir) => File(join(dir.path, 'tagline.json'))); - Future _saveTagLineToCache(final String json) async { - final File file = await _tagLineCacheFile; + Future _saveNewsToCache(final String json) async { + final File file = await _newsCacheFile; return file.writeAsString(json); } - bool _isTagLineCacheValid(File file) => + bool _isNewsCacheValid(File file) => file.existsSync() && file.lengthSync() > 0 && file @@ -172,7 +172,7 @@ class TagLineProvider extends ChangeNotifier { if (domain != _domain || prodEnv != _prodEnv) { _domain = domain; _prodEnv = prodEnv; - loadTagLine(forceUpdate: true); + loadLatestNews(forceUpdate: true); } } @@ -183,22 +183,22 @@ class TagLineProvider extends ChangeNotifier { } } -sealed class TagLineState { - const TagLineState(); +sealed class AppNewsState { + const AppNewsState(); } -final class TagLineLoading extends TagLineState { - const TagLineLoading(); +final class AppNewsStateLoading extends AppNewsState { + const AppNewsStateLoading(); } -class TagLineLoaded extends TagLineState { - const TagLineLoaded(this.tagLineContent); +class AppNewsStateLoaded extends AppNewsState { + const AppNewsStateLoaded(this.tagLineContent); - final TagLine tagLineContent; + final AppNews tagLineContent; } -class TagLineError extends TagLineState { - const TagLineError(this.exception); +class AppNewsStateError extends AppNewsState { + const AppNewsStateError(this.exception); final dynamic exception; } diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart index 4d629568009..93eb004619a 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart @@ -10,8 +10,8 @@ import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels/knowledge_panel_expanded_card.dart'; import 'package:smooth_app/knowledge_panel/knowledge_panels_builder.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -103,7 +103,7 @@ class _KnowledgePanelPageState extends State Future _refreshProduct(BuildContext context) async { try { final String? barcode = - ExternalCarouselManager.read(context).currentBarcode; + ExternalScanCarouselManager.read(context).currentBarcode; if (barcode?.isEmpty == true) { return; } diff --git a/packages/smooth_app/lib/main.dart b/packages/smooth_app/lib/main.dart index 66332c09516..f2577ae069e 100644 --- a/packages/smooth_app/lib/main.dart +++ b/packages/smooth_app/lib/main.dart @@ -16,9 +16,9 @@ import 'package:provider/single_child_widget.dart'; import 'package:scanner_shared/scanner_shared.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/data_models/product_preferences.dart'; -import 'package:smooth_app/data_models/tagline/tagline_provider.dart'; import 'package:smooth_app/data_models/user_management_provider.dart'; import 'package:smooth_app/database/dao_string.dart'; import 'package:smooth_app/database/local_database.dart'; @@ -237,8 +237,8 @@ class _SmoothAppState extends State { provide(_continuousScanModel), provide(_permissionListener), ], - child: ChangeNotifierProvider( - create: (BuildContext context) => TagLineProvider( + child: ChangeNotifierProvider( + create: (BuildContext context) => AppNewsProvider( context.read(), ), lazy: true, diff --git a/packages/smooth_app/lib/pages/navigator/app_navigator.dart b/packages/smooth_app/lib/pages/navigator/app_navigator.dart index 02c951306d0..68f33560b2b 100644 --- a/packages/smooth_app/lib/pages/navigator/app_navigator.dart +++ b/packages/smooth_app/lib/pages/navigator/app_navigator.dart @@ -3,12 +3,11 @@ import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/data_models/product_preferences.dart'; -import 'package:smooth_app/data_models/tagline/tagline_provider.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/extension_on_text_helper.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; import 'package:smooth_app/pages/guides/guide/guide_nutriscore_v2.dart'; import 'package:smooth_app/pages/navigator/error_page.dart'; import 'package:smooth_app/pages/navigator/external_page.dart'; @@ -18,6 +17,7 @@ import 'package:smooth_app/pages/product/add_new_product_page.dart'; import 'package:smooth_app/pages/product/edit_product_page.dart'; import 'package:smooth_app/pages/product/new_product_page.dart'; import 'package:smooth_app/pages/product/product_loader_page.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/pages/scan/search_page.dart'; import 'package:smooth_app/pages/scan/search_product_helper.dart'; import 'package:smooth_app/pages/user_management/sign_up_page.dart'; @@ -145,8 +145,8 @@ class _SmoothGoRouter { heroTag: state.uri.queryParameters['heroTag'], ); - if (ExternalCarouselManager.find(context) == null) { - return ExternalCarouselManager(child: widget); + if (ExternalScanCarouselManager.find(context) == null) { + return ExternalScanCarouselManager(child: widget); } else { return widget; } @@ -313,7 +313,7 @@ class _SmoothGoRouter { // Must be set first to ensure the method is only called once _appLanguageInitialized = true; ProductQuery.setLanguage(context, context.read()); - context.read().loadTagLine(); + context.read().loadLatestNews(); return context.read().refresh(); } diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart index 5cccb33335e..bdc88299518 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/database/local_database.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; import 'package:smooth_app/pages/navigator/app_navigator.dart'; import 'package:smooth_app/pages/onboarding/consent_analytics_page.dart'; import 'package:smooth_app/pages/onboarding/permissions_page.dart'; @@ -13,6 +12,7 @@ import 'package:smooth_app/pages/onboarding/sample_health_card_page.dart'; import 'package:smooth_app/pages/onboarding/scan_example.dart'; import 'package:smooth_app/pages/onboarding/welcome_page.dart'; import 'package:smooth_app/pages/page_manager.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; import 'package:smooth_app/widgets/will_pop_scope.dart'; @@ -114,7 +114,7 @@ enum OnboardingPage { ConsentAnalyticsPage(backgroundColor), ); case OnboardingPage.ONBOARDING_COMPLETE: - return ExternalCarouselManager(child: PageManager()); + return ExternalScanCarouselManager(child: PageManager()); } } diff --git a/packages/smooth_app/lib/pages/page_manager.dart b/packages/smooth_app/lib/pages/page_manager.dart index 615ee2500fb..5ef62fcfec1 100644 --- a/packages/smooth_app/lib/pages/page_manager.dart +++ b/packages/smooth_app/lib/pages/page_manager.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/widgets/tab_navigator.dart'; import 'package:smooth_app/widgets/will_pop_scope.dart'; @@ -62,8 +62,8 @@ class PageManagerState extends State { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); - final ExternalCarouselManagerState carouselManager = - ExternalCarouselManager.watch(context); + final ExternalScanCarouselManagerState carouselManager = + ExternalScanCarouselManager.watch(context); if (carouselManager.forceShowScannerTab) { _currentPage = BottomNavigationTab.Scan; diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_language_selector.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_language_selector.dart index 756706ee82b..6882d43bdbf 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_language_selector.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_language_selector.dart @@ -3,9 +3,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/background/background_task_language_refresh.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/data_models/product_preferences.dart'; -import 'package:smooth_app/data_models/tagline/tagline_provider.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/language_selector.dart'; @@ -57,9 +57,9 @@ class UserPreferencesLanguageSelector extends StatelessWidget { context.read(), ); - // Refresh the tagline + // Refresh the news feed if (context.mounted) { - context.read().loadTagLine(); + context.read().loadLatestNews(); } // TODO(monsieurtanuki): make it a background task also? // no await diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index 87cd95f4910..d831b6c70bc 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -21,7 +21,6 @@ import 'package:smooth_app/generic_lib/widgets/smooth_responsive.dart'; import 'package:smooth_app/helpers/app_helper.dart'; import 'package:smooth_app/helpers/robotoff_insight_helper.dart'; import 'package:smooth_app/pages/all_product_list_modal.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/pages/product/common/product_list_item_popup_items.dart'; import 'package:smooth_app/pages/product/common/product_list_item_simple.dart'; @@ -29,6 +28,7 @@ import 'package:smooth_app/pages/product/common/product_list_popup_items.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product_list_user_dialog_helper.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/query/product_query.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -133,7 +133,7 @@ class _ProductListPageState extends State icon: const Icon(CupertinoIcons.barcode), label: Text(appLocalizations.product_list_empty_title), onPressed: () => - ExternalCarouselManager.read(context).showSearchCard(), + ExternalScanCarouselManager.read(context).showSearchCard(), ) : _selectionMode ? null diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index f16cd8f68c8..ee44bec4fb5 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -21,7 +21,6 @@ import 'package:smooth_app/generic_lib/duration_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/pages/prices/prices_card.dart'; import 'package:smooth_app/pages/product/common/product_list_page.dart'; @@ -34,6 +33,7 @@ import 'package:smooth_app/pages/product/standard_knowledge_panel_cards.dart'; import 'package:smooth_app/pages/product/summary_card.dart'; import 'package:smooth_app/pages/product/website_card.dart'; import 'package:smooth_app/pages/product_list_user_dialog_helper.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/query/product_query.dart'; import 'package:smooth_app/themes/constant_icons.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -85,8 +85,8 @@ class _ProductPageState extends State @override Widget build(BuildContext context) { - final ExternalCarouselManagerState carouselManager = - ExternalCarouselManager.read(context); + final ExternalScanCarouselManagerState carouselManager = + ExternalScanCarouselManager.read(context); carouselManager.currentBarcode = barcode; final ThemeData themeData = Theme.of(context); _productPreferences = context.watch(); diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart new file mode 100644 index 00000000000..a693aecf8d5 --- /dev/null +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart @@ -0,0 +1,179 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_provider.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; +import 'package:smooth_app/helpers/provider_helper.dart'; +import 'package:smooth_app/helpers/strings_helper.dart'; +import 'package:smooth_app/pages/navigator/app_navigator.dart'; +import 'package:smooth_app/pages/scan/carousel/main_card/scan_tagline.dart'; +import 'package:smooth_app/resources/app_icons.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; + +class ScanMainCard extends StatelessWidget { + const ScanMainCard(); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Expanded( + child: ConsumerFilter( + buildWhen: + (AppNewsProvider? previousValue, AppNewsProvider currentValue) { + return previousValue?.hasContent != currentValue.hasContent; + }, + builder: (BuildContext context, AppNewsProvider newsFeed, _) { + if (!newsFeed.hasContent) { + return const _SearchCard( + expandedMode: true, + ); + } else { + return const Column( + children: [ + Expanded( + flex: 6, + child: _SearchCard( + expandedMode: false, + ), + ), + SizedBox(height: MEDIUM_SPACE), + Expanded( + flex: 4, + child: ScanTagLine(), + ), + ], + ); + } + }, + ), + ), + ], + ); + } +} + +class _SearchCard extends StatelessWidget { + const _SearchCard({ + required this.expandedMode, + }); + + /// Expanded is when this card is the only one (no tagline, no app review…) + final bool expandedMode; + + @override + Widget build(BuildContext context) { + final AppLocalizations localizations = AppLocalizations.of(context); + final bool lightTheme = !context.watch().isDarkMode(context); + + final Widget widget = SmoothCard( + color: lightTheme ? Colors.grey.withOpacity(0.1) : Colors.black, + padding: const EdgeInsets.symmetric( + vertical: MEDIUM_SPACE, + horizontal: LARGE_SPACE, + ), + margin: const EdgeInsets.symmetric( + horizontal: 0.0, + vertical: VERY_SMALL_SPACE, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SvgPicture.asset( + lightTheme + ? 'assets/app/logo_text_black.svg' + : 'assets/app/logo_text_white.svg', + semanticsLabel: localizations.homepage_main_card_logo_description, + ), + FormattedText( + text: localizations.homepage_main_card_subheading, + textAlign: TextAlign.center, + textStyle: const TextStyle(height: 1.3), + ), + const _SearchBar(), + ], + ), + ); + + if (expandedMode) { + return ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.sizeOf(context).height * 0.4, + ), + child: widget, + ); + } else { + return widget; + } + } +} + +class _SearchBar extends StatelessWidget { + const _SearchBar(); + + static const double SEARCH_BAR_HEIGHT = 47.0; + + @override + Widget build(BuildContext context) { + final AppLocalizations localizations = AppLocalizations.of(context); + final SmoothColorsThemeExtension theme = + Theme.of(context).extension()!; + final bool lightTheme = !context.watch().isDarkMode(context); + + return SizedBox( + height: SEARCH_BAR_HEIGHT, + child: InkWell( + onTap: () => AppNavigator.of(context).push(AppRoutes.SEARCH), + borderRadius: BorderRadius.circular(30.0), + child: Ink( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + color: lightTheme ? Colors.white : theme.greyDark, + border: Border.all(color: theme.primaryBlack), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.only( + start: 20.0, + end: 10.0, + bottom: 3.0, + ), + child: Text( + localizations.homepage_main_card_search_field_hint, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: lightTheme ? Colors.black : Colors.white, + ), + ), + ), + ), + AspectRatio( + aspectRatio: 1.0, + child: DecoratedBox( + decoration: BoxDecoration( + color: theme.primaryDark, + shape: BoxShape.circle, + ), + child: const Padding( + padding: EdgeInsets.all(10.0), + child: Search( + size: 20.0, + color: Colors.white, + ), + ), + ), + ) + ], + ), + ), + ), + ); + } +} diff --git a/packages/smooth_app/lib/pages/scan/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart similarity index 87% rename from packages/smooth_app/lib/pages/scan/scan_tagline.dart rename to packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart index 8fabda2f8a8..cbd3869f349 100644 --- a/packages/smooth_app/lib/pages/scan/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart @@ -5,9 +5,9 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'package:shimmer/shimmer.dart'; import 'package:smooth_app/cards/category_cards/svg_cache.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_model.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; -import 'package:smooth_app/data_models/tagline/tagline_model.dart'; -import 'package:smooth_app/data_models/tagline/tagline_provider.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/helpers/launch_url_helper.dart'; @@ -22,12 +22,12 @@ class ScanTagLine extends StatelessWidget { @override Widget build(BuildContext context) { - return ChangeNotifierProvider<_ScanTagLineProvider>( - create: (BuildContext context) => _ScanTagLineProvider(context), - child: Consumer<_ScanTagLineProvider>( + return ChangeNotifierProvider<_ScanNewsFeedProvider>( + create: (BuildContext context) => _ScanNewsFeedProvider(context), + child: Consumer<_ScanNewsFeedProvider>( builder: ( BuildContext context, - _ScanTagLineProvider scanTagLineProvider, + _ScanNewsFeedProvider scanTagLineProvider, Widget? child, ) { final _ScanTagLineState state = scanTagLineProvider.value; @@ -70,7 +70,7 @@ class _ScanTagLineContent extends StatefulWidget { required this.news, }); - final Iterable news; + final Iterable news; @override State<_ScanTagLineContent> createState() => _ScanTagLineContentState(); @@ -102,7 +102,7 @@ class _ScanTagLineContentState extends State<_ScanTagLineContent> { final ThemeProvider themeProvider = context.watch(); final SmoothColorsThemeExtension theme = Theme.of(context).extension()!; - final TagLineNewsItem currentNews = widget.news.elementAt(_index); + final AppNewsItem currentNews = widget.news.elementAt(_index); // Default values seem weird const Radius radius = Radius.circular(16.0); @@ -241,7 +241,7 @@ class _TagLineContentBody extends StatelessWidget { final String message; final Color? textColor; - final TagLineImage? image; + final AppNewsImage? image; @override Widget build(BuildContext context) { @@ -346,49 +346,49 @@ class _TagLineContentButton extends StatelessWidget { } } -/// Listen to [TagLineProvider] feed and provide a list of [TagLineNewsItem] +/// Listen to [AppNewsProvider] feed and provide a list of [AppNewsItem] /// randomly sorted by unread, then displayed and clicked news. -class _ScanTagLineProvider extends ValueNotifier<_ScanTagLineState> { - _ScanTagLineProvider(BuildContext context) - : _tagLineProvider = context.read(), +class _ScanNewsFeedProvider extends ValueNotifier<_ScanTagLineState> { + _ScanNewsFeedProvider(BuildContext context) + : _newsFeedProvider = context.read(), _userPreferences = context.read(), super(const _ScanTagLineStateLoading()) { - _tagLineProvider.addListener(_onTagLineStateChanged); + _newsFeedProvider.addListener(_onNewsFeedStateChanged); // Refresh with the current state - _onTagLineStateChanged(); + _onNewsFeedStateChanged(); } - final TagLineProvider _tagLineProvider; + final AppNewsProvider _newsFeedProvider; final UserPreferences _userPreferences; - void _onTagLineStateChanged() { - switch (_tagLineProvider.state) { - case TagLineLoading(): + void _onNewsFeedStateChanged() { + switch (_newsFeedProvider.state) { + case AppNewsStateLoading(): emit(const _ScanTagLineStateLoading()); - case TagLineError(): + case AppNewsStateError(): emit(const _ScanTagLineStateNoContent()); - case TagLineLoaded(): + case AppNewsStateLoaded(): _onTagLineContentAvailable( - (_tagLineProvider.state as TagLineLoaded).tagLineContent); + (_newsFeedProvider.state as AppNewsStateLoaded).tagLineContent); } } - Future _onTagLineContentAvailable(TagLine tagLine) async { + Future _onTagLineContentAvailable(AppNews tagLine) async { if (!tagLine.feed.isNotEmpty) { emit(const _ScanTagLineStateNoContent()); return; } - final List unreadNews = []; - final List displayedNews = []; - final List clickedNews = []; + final List unreadNews = []; + final List displayedNews = []; + final List clickedNews = []; final List taglineFeedAlreadyClickedNews = _userPreferences.taglineFeedClickedNews; final List taglineFeedAlreadyDisplayedNews = _userPreferences.taglineFeedDisplayedNews; - for (final TagLineFeedItem feedItem in tagLine.feed.news) { + for (final AppNewsFeedItem feedItem in tagLine.feed.news) { if (taglineFeedAlreadyClickedNews.contains(feedItem.id)) { clickedNews.add(feedItem.news); } else if (taglineFeedAlreadyDisplayedNews.contains(feedItem.id)) { @@ -400,7 +400,7 @@ class _ScanTagLineProvider extends ValueNotifier<_ScanTagLineState> { emit( _ScanTagLineStateLoaded( - [ + [ ...unreadNews..shuffle(), ...displayedNews..shuffle(), ...clickedNews..shuffle(), @@ -411,7 +411,7 @@ class _ScanTagLineProvider extends ValueNotifier<_ScanTagLineState> { @override void dispose() { - _tagLineProvider.removeListener(_onTagLineStateChanged); + _newsFeedProvider.removeListener(_onNewsFeedStateChanged); super.dispose(); } } @@ -431,5 +431,5 @@ class _ScanTagLineStateNoContent extends _ScanTagLineState { class _ScanTagLineStateLoaded extends _ScanTagLineState { const _ScanTagLineStateLoaded(this.tagLine); - final Iterable tagLine; + final Iterable tagLine; } diff --git a/packages/smooth_app/lib/pages/scan/carousel/scan_carousel.dart b/packages/smooth_app/lib/pages/scan/carousel/scan_carousel.dart new file mode 100644 index 00000000000..6ab2e199366 --- /dev/null +++ b/packages/smooth_app/lib/pages/scan/carousel/scan_carousel.dart @@ -0,0 +1,195 @@ +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:scanner_shared/scanner_shared.dart' hide EMPTY_WIDGET; +import 'package:smooth_app/cards/product_cards/smooth_product_card_error.dart'; +import 'package:smooth_app/cards/product_cards/smooth_product_card_loading.dart'; +import 'package:smooth_app/cards/product_cards/smooth_product_card_not_found.dart'; +import 'package:smooth_app/cards/product_cards/smooth_product_card_thanks.dart'; +import 'package:smooth_app/data_models/continuous_scan_model.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/pages/scan/carousel/main_card/scan_main_card.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; +import 'package:smooth_app/pages/scan/scan_product_card_loader.dart'; + +class ScanPageCarousel extends StatefulWidget { + const ScanPageCarousel({ + this.onPageChangedTo, + }); + + final Function(int page, String? productBarcode)? onPageChangedTo; + + @override + State createState() => _ScanPageCarouselState(); +} + +class _ScanPageCarouselState extends State { + static const double HORIZONTAL_SPACE_BETWEEN_CARDS = 5.0; + + List barcodes = []; + String? _lastConsultedBarcode; + int? _carrouselMovingTo; + int _lastIndex = 0; + + late ContinuousScanModel _model; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _model = context.watch(); + + if (!ExternalScanCarouselManager.read(context).controller.ready) { + return; + } + + barcodes = _model.getBarcodes(); + + if (barcodes.isEmpty) { + // Ensure to reset all variables + _lastConsultedBarcode = null; + _carrouselMovingTo = null; + _lastIndex = 0; + return; + } else if (_lastConsultedBarcode == _model.latestConsultedBarcode) { + // Prevent multiple irrelevant movements + return; + } + + _lastConsultedBarcode = _model.latestConsultedBarcode; + final int cardsCount = barcodes.length + 1; + + if (_model.latestConsultedBarcode != null && + _model.latestConsultedBarcode!.isNotEmpty) { + final int indexBarcode = barcodes.indexOf(_model.latestConsultedBarcode!); + if (indexBarcode >= 0) { + final int indexCarousel = indexBarcode + 1; + _moveControllerTo(indexCarousel); + } else { + if (_lastIndex > cardsCount) { + _moveControllerTo(cardsCount); + } else { + _moveControllerTo(_lastIndex); + } + } + } else { + _moveControllerTo(0); + } + } + + Future _moveControllerTo(int page) async { + if (_carrouselMovingTo == null && _lastIndex != page) { + widget.onPageChangedTo?.call( + page, + page >= 1 ? barcodes[page - 1] : null, + ); + + _carrouselMovingTo = page; + ExternalScanCarouselManager.read(context).animatePageTo(page); + _carrouselMovingTo = null; + } + } + + @override + Widget build(BuildContext context) { + barcodes = _model.getBarcodes(); + + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return CarouselSlider.builder( + itemCount: barcodes.length + 1, + itemBuilder: + (BuildContext context, int itemIndex, int itemRealIndex) { + return SizedBox.expand( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: HORIZONTAL_SPACE_BETWEEN_CARDS, + ), + child: itemIndex == 0 + ? const ScanMainCard() + : _getWidget(itemIndex - 1), + ), + ); + }, + carouselController: + ExternalScanCarouselManager.watch(context).controller, + options: CarouselOptions( + enlargeCenterPage: false, + viewportFraction: _computeViewPortFraction(), + height: constraints.maxHeight, + enableInfiniteScroll: false, + onPageChanged: (int index, CarouselPageChangedReason reason) { + _lastIndex = index; + + if (index > 0) { + if (reason == CarouselPageChangedReason.manual) { + _model.lastConsultedBarcode = barcodes[index - 1]; + _lastConsultedBarcode = _model.latestConsultedBarcode; + } + } else if (index == 0) { + _model.lastConsultedBarcode = null; + _lastConsultedBarcode = null; + } + }, + ), + ); + }, + ); + } + + /// Displays the card for this [index] of a list of [barcodes] + /// + /// There are special cases when the item display is refreshed + /// after the product disappeared and before the whole carousel is refreshed. + /// In those cases, we don't want the app to crash and display a Container + /// instead in the meanwhile. + Widget _getWidget(final int index) { + if (index >= barcodes.length) { + return EMPTY_WIDGET; + } + final String barcode = barcodes[index]; + switch (_model.getBarcodeState(barcode)!) { + case ScannedProductState.FOUND: + case ScannedProductState.CACHED: + return ScanProductCardLoader(barcode); + case ScannedProductState.LOADING: + return SmoothProductCardLoading( + barcode: barcode, + onRemoveProduct: (_) => _model.removeBarcode(barcode), + ); + case ScannedProductState.NOT_FOUND: + return SmoothProductCardNotFound( + barcode: barcode, + onAddProduct: () async { + await _model.refresh(); + setState(() {}); + }, + onRemoveProduct: (_) => _model.removeBarcode(barcode), + ); + case ScannedProductState.THANKS: + return const SmoothProductCardThanks(); + case ScannedProductState.ERROR_INTERNET: + return SmoothProductCardError( + barcode: barcode, + errorType: ScannedProductState.ERROR_INTERNET, + ); + case ScannedProductState.ERROR_INVALID_CODE: + return SmoothProductCardError( + barcode: barcode, + errorType: ScannedProductState.ERROR_INVALID_CODE, + ); + } + } + + double _computeViewPortFraction() { + final double screenWidth = MediaQuery.sizeOf(context).width; + if (barcodes.isEmpty) { + return 0.95; + } + + return (screenWidth - + (SmoothBarcodeScannerVisor.CORNER_PADDING * 2) - + (SmoothBarcodeScannerVisor.STROKE_WIDTH * 2) + + (HORIZONTAL_SPACE_BETWEEN_CARDS * 4)) / + screenWidth; + } +} diff --git a/packages/smooth_app/lib/pages/carousel_manager.dart b/packages/smooth_app/lib/pages/scan/carousel/scan_carousel_manager.dart similarity index 75% rename from packages/smooth_app/lib/pages/carousel_manager.dart rename to packages/smooth_app/lib/pages/scan/carousel/scan_carousel_manager.dart index d3ad42eadf4..02bccf79825 100644 --- a/packages/smooth_app/lib/pages/carousel_manager.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/scan_carousel_manager.dart @@ -2,36 +2,38 @@ import 'package:carousel_slider/carousel_controller.dart'; import 'package:flutter/material.dart'; import 'package:smooth_app/helpers/haptic_feedback_helper.dart'; -class ExternalCarouselManager extends StatefulWidget { - const ExternalCarouselManager({ +/// Allow to control the [ScanPageCarousel] from outside +class ExternalScanCarouselManager extends StatefulWidget { + const ExternalScanCarouselManager({ super.key, required this.child, }); final Widget child; - static ExternalCarouselManagerState watch(BuildContext context) { + static ExternalScanCarouselManagerState watch(BuildContext context) { return context .dependOnInheritedWidgetOfExactType<_InheritedCarouselManager>()! .state; } - static ExternalCarouselManagerState? find(BuildContext context) { + static ExternalScanCarouselManagerState? find(BuildContext context) { return context .findAncestorWidgetOfExactType<_InheritedCarouselManager>() ?.state; } - static ExternalCarouselManagerState read(BuildContext context) { + static ExternalScanCarouselManagerState read(BuildContext context) { return find(context)!; } @override - State createState() => - ExternalCarouselManagerState(); + State createState() => + ExternalScanCarouselManagerState(); } -class ExternalCarouselManagerState extends State { +class ExternalScanCarouselManagerState + extends State { final CarouselController _controller = CarouselController(); /// A hidden attribute to force to return to the Scanner tab @@ -75,7 +77,7 @@ class ExternalCarouselManagerState extends State { CarouselController get controller => _controller; - bool updateShouldNotify(ExternalCarouselManagerState oldState) { + bool updateShouldNotify(ExternalScanCarouselManagerState oldState) { return oldState.currentBarcode != currentBarcode || _forceShowScannerTab; } } @@ -87,7 +89,7 @@ class _InheritedCarouselManager extends InheritedWidget { Key? key, }) : super(key: key, child: child); - final ExternalCarouselManagerState state; + final ExternalScanCarouselManagerState state; @override bool updateShouldNotify(_InheritedCarouselManager oldWidget) { diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index 500972deb9c..f1a4f4401ea 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -15,7 +15,7 @@ import 'package:smooth_app/helpers/camera_helper.dart'; import 'package:smooth_app/helpers/haptic_feedback_helper.dart'; import 'package:smooth_app/helpers/permission_helper.dart'; import 'package:smooth_app/pages/scan/camera_scan_page.dart'; -import 'package:smooth_app/widgets/smooth_product_carousel.dart'; +import 'package:smooth_app/pages/scan/carousel/scan_carousel.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; class ScanPage extends StatefulWidget { @@ -92,8 +92,7 @@ class _ScanPageState extends State { flex: _carouselHeightPct, child: Padding( padding: const EdgeInsetsDirectional.only(bottom: 10.0), - child: SmoothProductCarousel( - containSearchCard: true, + child: ScanPageCarousel( onPageChangedTo: (int page, String? barcode) async { if (barcode == null) { // We only notify for new products diff --git a/packages/smooth_app/lib/widgets/smooth_product_carousel.dart b/packages/smooth_app/lib/widgets/smooth_product_carousel.dart deleted file mode 100644 index d5d806235c0..00000000000 --- a/packages/smooth_app/lib/widgets/smooth_product_carousel.dart +++ /dev/null @@ -1,375 +0,0 @@ -import 'package:carousel_slider/carousel_slider.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:provider/provider.dart'; -import 'package:scanner_shared/scanner_shared.dart' hide EMPTY_WIDGET; -import 'package:smooth_app/cards/product_cards/smooth_product_card_error.dart'; -import 'package:smooth_app/cards/product_cards/smooth_product_card_loading.dart'; -import 'package:smooth_app/cards/product_cards/smooth_product_card_not_found.dart'; -import 'package:smooth_app/cards/product_cards/smooth_product_card_thanks.dart'; -import 'package:smooth_app/data_models/continuous_scan_model.dart'; -import 'package:smooth_app/data_models/tagline/tagline_provider.dart'; -import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; -import 'package:smooth_app/helpers/provider_helper.dart'; -import 'package:smooth_app/helpers/strings_helper.dart'; -import 'package:smooth_app/pages/carousel_manager.dart'; -import 'package:smooth_app/pages/navigator/app_navigator.dart'; -import 'package:smooth_app/pages/scan/scan_product_card_loader.dart'; -import 'package:smooth_app/pages/scan/scan_tagline.dart'; -import 'package:smooth_app/resources/app_icons.dart'; -import 'package:smooth_app/themes/smooth_theme_colors.dart'; -import 'package:smooth_app/themes/theme_provider.dart'; - -class SmoothProductCarousel extends StatefulWidget { - const SmoothProductCarousel({ - this.containSearchCard = false, - this.onPageChangedTo, - }); - - final bool containSearchCard; - final Function(int page, String? productBarcode)? onPageChangedTo; - - @override - State createState() => _SmoothProductCarouselState(); -} - -class _SmoothProductCarouselState extends State { - static const double HORIZONTAL_SPACE_BETWEEN_CARDS = 5.0; - - List barcodes = []; - String? _lastConsultedBarcode; - int? _carrouselMovingTo; - int _lastIndex = 0; - - int get _searchCardAdjustment => widget.containSearchCard ? 1 : 0; - late ContinuousScanModel _model; - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _model = context.watch(); - - if (!ExternalCarouselManager.read(context).controller.ready) { - return; - } - - barcodes = _model.getBarcodes(); - - if (barcodes.isEmpty) { - // Ensure to reset all variables - _lastConsultedBarcode = null; - _carrouselMovingTo = null; - _lastIndex = 0; - return; - } else if (_lastConsultedBarcode == _model.latestConsultedBarcode) { - // Prevent multiple irrelevant movements - return; - } - - _lastConsultedBarcode = _model.latestConsultedBarcode; - final int cardsCount = barcodes.length + _searchCardAdjustment; - - if (_model.latestConsultedBarcode != null && - _model.latestConsultedBarcode!.isNotEmpty) { - final int indexBarcode = barcodes.indexOf(_model.latestConsultedBarcode!); - if (indexBarcode >= 0) { - final int indexCarousel = indexBarcode + _searchCardAdjustment; - _moveControllerTo(indexCarousel); - } else { - if (_lastIndex > cardsCount) { - _moveControllerTo(cardsCount); - } else { - _moveControllerTo(_lastIndex); - } - } - } else { - _moveControllerTo(0); - } - } - - Future _moveControllerTo(int page) async { - if (_carrouselMovingTo == null && _lastIndex != page) { - widget.onPageChangedTo?.call( - page, - page >= _searchCardAdjustment - ? barcodes[page - _searchCardAdjustment] - : null, - ); - - _carrouselMovingTo = page; - ExternalCarouselManager.read(context).animatePageTo(page); - _carrouselMovingTo = null; - } - } - - @override - Widget build(BuildContext context) { - barcodes = _model.getBarcodes(); - - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return CarouselSlider.builder( - itemCount: barcodes.length + _searchCardAdjustment, - itemBuilder: - (BuildContext context, int itemIndex, int itemRealIndex) { - return SizedBox.expand( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: HORIZONTAL_SPACE_BETWEEN_CARDS, - ), - child: widget.containSearchCard && itemIndex == 0 - ? const _MainCard() - : _getWidget(itemIndex - _searchCardAdjustment), - ), - ); - }, - carouselController: ExternalCarouselManager.watch(context).controller, - options: CarouselOptions( - enlargeCenterPage: false, - viewportFraction: _computeViewPortFraction(), - height: constraints.maxHeight, - enableInfiniteScroll: false, - onPageChanged: (int index, CarouselPageChangedReason reason) { - _lastIndex = index; - - if (index > 0) { - if (reason == CarouselPageChangedReason.manual) { - _model.lastConsultedBarcode = - barcodes[index - _searchCardAdjustment]; - _lastConsultedBarcode = _model.latestConsultedBarcode; - } - } else if (index == 0) { - _model.lastConsultedBarcode = null; - _lastConsultedBarcode = null; - } - }, - ), - ); - }, - ); - } - - /// Displays the card for this [index] of a list of [barcodes] - /// - /// There are special cases when the item display is refreshed - /// after the product disappeared and before the whole carousel is refreshed. - /// In those cases, we don't want the app to crash and display a Container - /// instead in the meanwhile. - Widget _getWidget(final int index) { - if (index >= barcodes.length) { - return EMPTY_WIDGET; - } - final String barcode = barcodes[index]; - switch (_model.getBarcodeState(barcode)!) { - case ScannedProductState.FOUND: - case ScannedProductState.CACHED: - return ScanProductCardLoader(barcode); - case ScannedProductState.LOADING: - return SmoothProductCardLoading( - barcode: barcode, - onRemoveProduct: (_) => _model.removeBarcode(barcode), - ); - case ScannedProductState.NOT_FOUND: - return SmoothProductCardNotFound( - barcode: barcode, - onAddProduct: () async { - await _model.refresh(); - setState(() {}); - }, - onRemoveProduct: (_) => _model.removeBarcode(barcode), - ); - case ScannedProductState.THANKS: - return const SmoothProductCardThanks(); - case ScannedProductState.ERROR_INTERNET: - return SmoothProductCardError( - barcode: barcode, - errorType: ScannedProductState.ERROR_INTERNET, - ); - case ScannedProductState.ERROR_INVALID_CODE: - return SmoothProductCardError( - barcode: barcode, - errorType: ScannedProductState.ERROR_INVALID_CODE, - ); - } - } - - double _computeViewPortFraction() { - final double screenWidth = MediaQuery.sizeOf(context).width; - if (barcodes.isEmpty) { - return 0.95; - } - - return (screenWidth - - (SmoothBarcodeScannerVisor.CORNER_PADDING * 2) - - (SmoothBarcodeScannerVisor.STROKE_WIDTH * 2) + - (HORIZONTAL_SPACE_BETWEEN_CARDS * 4)) / - screenWidth; - } -} - -class _MainCard extends StatelessWidget { - const _MainCard(); - - @override - Widget build(BuildContext context) { - return Column( - children: [ - Expanded( - child: ConsumerFilter( - buildWhen: - (TagLineProvider? previousValue, TagLineProvider currentValue) { - return previousValue?.hasContent != currentValue.hasContent; - }, - builder: (BuildContext context, TagLineProvider tagLineManager, _) { - if (!tagLineManager.hasContent) { - return const _SearchCard( - expandedMode: true, - ); - } else { - return const Column( - children: [ - Expanded( - flex: 6, - child: _SearchCard( - expandedMode: false, - ), - ), - SizedBox(height: MEDIUM_SPACE), - Expanded( - flex: 4, - child: ScanTagLine(), - ), - ], - ); - } - }, - ), - ), - ], - ); - } -} - -class _SearchCard extends StatelessWidget { - const _SearchCard({ - required this.expandedMode, - }); - - /// Expanded is when this card is the only one (no tagline, no app review…) - final bool expandedMode; - - @override - Widget build(BuildContext context) { - final AppLocalizations localizations = AppLocalizations.of(context); - final bool lightTheme = !context.watch().isDarkMode(context); - - final Widget widget = SmoothCard( - color: lightTheme ? Colors.grey.withOpacity(0.1) : Colors.black, - padding: const EdgeInsets.symmetric( - vertical: MEDIUM_SPACE, - horizontal: LARGE_SPACE, - ), - margin: const EdgeInsets.symmetric( - horizontal: 0.0, - vertical: VERY_SMALL_SPACE, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - SvgPicture.asset( - lightTheme - ? 'assets/app/logo_text_black.svg' - : 'assets/app/logo_text_white.svg', - semanticsLabel: localizations.homepage_main_card_logo_description, - ), - FormattedText( - text: localizations.homepage_main_card_subheading, - textAlign: TextAlign.center, - textStyle: const TextStyle(height: 1.3), - ), - const _SearchBar(), - ], - ), - ); - - if (expandedMode) { - return ConstrainedBox( - constraints: BoxConstraints( - maxHeight: MediaQuery.sizeOf(context).height * 0.4, - ), - child: widget, - ); - } else { - return widget; - } - } -} - -class _SearchBar extends StatelessWidget { - const _SearchBar(); - - static const double SEARCH_BAR_HEIGHT = 47.0; - - @override - Widget build(BuildContext context) { - final AppLocalizations localizations = AppLocalizations.of(context); - final SmoothColorsThemeExtension theme = - Theme.of(context).extension()!; - final bool lightTheme = !context.watch().isDarkMode(context); - - return SizedBox( - height: SEARCH_BAR_HEIGHT, - child: InkWell( - onTap: () => AppNavigator.of(context).push(AppRoutes.SEARCH), - borderRadius: BorderRadius.circular(30.0), - child: Ink( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30.0), - color: lightTheme ? Colors.white : theme.greyDark, - border: Border.all(color: theme.primaryBlack), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsetsDirectional.only( - start: 20.0, - end: 10.0, - bottom: 3.0, - ), - child: Text( - localizations.homepage_main_card_search_field_hint, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: lightTheme ? Colors.black : Colors.white, - ), - ), - ), - ), - AspectRatio( - aspectRatio: 1.0, - child: DecoratedBox( - decoration: BoxDecoration( - color: theme.primaryDark, - shape: BoxShape.circle, - ), - child: const Padding( - padding: EdgeInsets.all(10.0), - child: Search( - size: 20.0, - color: Colors.white, - ), - ), - ), - ) - ], - ), - ), - ), - ); - } -} From 65ce9c45ce40ab6f2caa7dfadc57be4092174e37 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sun, 16 Jun 2024 18:38:30 +0200 Subject: [PATCH 18/85] feat: Extract ingredients/packaging: loading / loaded / extracting states (#5384) * Extract ingredients/packaging: loading / loaded / extracting states * Extractingdata variable can be private * Tiny perf improvement * Fix Lint --- packages/smooth_app/lib/l10n/app_en.arb | 22 +- .../lib/pages/product/edit_ocr_page.dart | 248 ++++++++++++++++-- .../lib/pages/product/ocr_helper.dart | 6 + .../pages/product/ocr_ingredients_helper.dart | 10 +- .../pages/product/ocr_packaging_helper.dart | 8 + 5 files changed, 275 insertions(+), 19 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 4bf432693ef..365f0483080 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1448,18 +1448,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" diff --git a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr_page.dart index 4331a249eea..d9d48af0e93 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; +import 'package:shimmer/shimmer.dart'; import 'package:smooth_app/background/background_task_details.dart'; import 'package:smooth_app/data_models/up_to_date_mixin.dart'; import 'package:smooth_app/database/local_database.dart'; @@ -18,6 +19,7 @@ import 'package:smooth_app/pages/product/explanation_widget.dart'; import 'package:smooth_app/pages/product/multilingual_helper.dart'; import 'package:smooth_app/pages/product/ocr_helper.dart'; import 'package:smooth_app/pages/product/product_image_button.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; /// Editing with OCR a product field and the corresponding image. @@ -43,6 +45,7 @@ class _EditOcrPageState extends State with UpToDateMixin { late final MultilingualHelper _multilingualHelper; OcrHelper get _helper => widget.helper; + bool _extractingData = false; @override void initState() { @@ -62,7 +65,8 @@ class _EditOcrPageState extends State with UpToDateMixin { /// /// When done, populates the related page field. Future _extractData() async { - // TODO(monsieurtanuki): hide the "extract" button while extracting, or display a loading dialog on top + setState(() => _extractingData = true); + try { final String? extractedText = await _helper.getExtractedText( widget.product, @@ -72,6 +76,8 @@ class _EditOcrPageState extends State with UpToDateMixin { return; } + setState(() => _extractingData = false); + if (extractedText == null || extractedText.isEmpty) { await LoadingDialog.error( context: context, @@ -83,9 +89,7 @@ class _EditOcrPageState extends State with UpToDateMixin { if (_controller.text != extractedText) { setState(() => _controller.text = extractedText); } - } catch (e) { - // - } + } catch (_) {} } /// Updates the product field on the server. @@ -282,17 +286,11 @@ class _EditOcrPageState extends State with UpToDateMixin { setState: setState, product: upToDateProduct, ), - if (transientFile.isServerImage()) - SmoothActionButtonsBar.single( - action: SmoothActionButton( - text: - _helper.getActionExtractText(appLocalizations), - onPressed: () async => _extractData(), - ), - ) - else if (transientFile.isImageAvailable()) - // TODO(monsieurtanuki): what if slow upload? text instead? - const CircularProgressIndicator.adaptive(), + _EditOcrMainAction( + onPressed: _extractData, + helper: _helper, + state: _extractState(transientFile), + ), const SizedBox(height: MEDIUM_SPACE), TextField( controller: _controller, @@ -377,4 +375,224 @@ class _EditOcrPageState extends State with UpToDateMixin { } return result; } + + OcrState _extractState(TransientFile transientFile) { + if (_extractingData) { + return OcrState.EXTRACTING_DATA; + } else if (transientFile.isServerImage()) { + return OcrState.IMAGE_LOADED; + } else if (transientFile.isImageAvailable()) { + return OcrState.IMAGE_LOADING; + } else { + return OcrState.OTHER; + } + } +} + +class _EditOcrMainAction extends StatelessWidget { + const _EditOcrMainAction({ + required this.onPressed, + required this.helper, + required this.state, + }); + + final VoidCallback onPressed; + final OcrHelper helper; + final OcrState state; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + + final Widget? child = switch (state) { + OcrState.IMAGE_LOADING => _EditOcrActionLoadingContent( + helper: helper, + appLocalizations: appLocalizations, + ), + OcrState.IMAGE_LOADED => _ExtractMainActionContentLoaded( + helper: helper, + appLocalizations: appLocalizations, + onPressed: onPressed, + ), + OcrState.EXTRACTING_DATA => _EditOcrActionExtractingContent( + helper: helper, + appLocalizations: appLocalizations, + ), + OcrState.OTHER => null, + }; + + if (child == null) { + return EMPTY_WIDGET; + } + + final SmoothColorsThemeExtension theme = + Theme.of(context).extension()!; + + return SizedBox( + height: 45.0 * (_computeFontScaleFactor(context)), + width: double.infinity, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: ANGULAR_BORDER_RADIUS, + color: theme.primarySemiDark, + border: Border.all( + color: theme.primaryBlack, + width: 2.0, + ), + ), + child: Material( + type: MaterialType.transparency, + child: ProgressIndicatorTheme( + data: const ProgressIndicatorThemeData( + color: Colors.white, + ), + child: IconTheme( + data: const IconThemeData(color: Colors.white), + child: DefaultTextStyle( + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15.5, + color: Colors.white, + ), + child: child, + ), + ), + ), + ), + ), + ); + } + + double _computeFontScaleFactor(BuildContext context) { + final double fontSize = DefaultTextStyle.of(context).style.fontSize ?? 15.0; + final double scaledFontSize = + MediaQuery.textScalerOf(context).scale(fontSize); + + return scaledFontSize / fontSize; + } +} + +class _EditOcrActionExtractingContent extends StatelessWidget { + const _EditOcrActionExtractingContent({ + required this.helper, + required this.appLocalizations, + }); + + final OcrHelper helper; + final AppLocalizations appLocalizations; + + @override + Widget build(BuildContext context) { + return Semantics( + label: helper.getActionLoadingPhoto(appLocalizations), + excludeSemantics: true, + child: Shimmer( + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Colors.black, + Colors.white, + Colors.black, + ], + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator.adaptive(), + Expanded( + child: Text( + helper.getActionExtractingData(appLocalizations), + textAlign: TextAlign.center, + ), + ), + const CircularProgressIndicator.adaptive(), + ], + ), + ), + ), + ); + } +} + +class _ExtractMainActionContentLoaded extends StatelessWidget { + const _ExtractMainActionContentLoaded({ + required this.helper, + required this.appLocalizations, + required this.onPressed, + }); + + final OcrHelper helper; + final AppLocalizations appLocalizations; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return Semantics( + excludeSemantics: true, + value: helper.getActionExtractText(appLocalizations), + button: true, + child: InkWell( + onTap: onPressed, + borderRadius: ANGULAR_BORDER_RADIUS, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Text( + helper.getActionExtractText(appLocalizations), + ), + ), + const Icon( + Icons.download, + semanticLabel: '', + ), + ], + ), + ), + ), + ); + } +} + +class _EditOcrActionLoadingContent extends StatelessWidget { + const _EditOcrActionLoadingContent({ + required this.helper, + required this.appLocalizations, + }); + + final OcrHelper helper; + final AppLocalizations appLocalizations; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Text( + helper.getActionLoadingPhoto(appLocalizations), + ), + ), + const CircularProgressIndicator.adaptive(), + ], + ), + ); + } +} + +enum OcrState { + IMAGE_LOADING, + IMAGE_LOADED, + EXTRACTING_DATA, + OTHER, } diff --git a/packages/smooth_app/lib/pages/product/ocr_helper.dart b/packages/smooth_app/lib/pages/product/ocr_helper.dart index 61b5b2cc33c..2a232e05e04 100644 --- a/packages/smooth_app/lib/pages/product/ocr_helper.dart +++ b/packages/smooth_app/lib/pages/product/ocr_helper.dart @@ -39,6 +39,12 @@ abstract class OcrHelper { /// Returns the "extract text" button label String getActionExtractText(final AppLocalizations appLocalizations); + /// Returns the "loading photo" button label + String getActionLoadingPhoto(final AppLocalizations appLocalizations); + + /// Returns the "Extracting data…" button label + String getActionExtractingData(final AppLocalizations appLocalizations); + /// Returns the "refresh photo" button label String getActionRefreshPhoto(final AppLocalizations appLocalizations); diff --git a/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart b/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart index 6f1eeb8a48d..1421d5a70d8 100644 --- a/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart +++ b/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart @@ -43,7 +43,15 @@ class OcrIngredientsHelper extends OcrHelper { @override String getActionExtractText(final AppLocalizations appLocalizations) => - appLocalizations.edit_ingredients_extrait_ingredients_btn_text; + appLocalizations.edit_ingredients_extract_ingredients_btn_text; + + @override + String getActionExtractingData(AppLocalizations appLocalizations) => + appLocalizations.edit_ingredients_extracting_ingredients_btn_text; + + @override + String getActionLoadingPhoto(AppLocalizations appLocalizations) => + appLocalizations.edit_ingredients_loading_photo_btn_text; @override String getActionRefreshPhoto(final AppLocalizations appLocalizations) => diff --git a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart b/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart index 179adefe296..600e24a7563 100644 --- a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart +++ b/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart @@ -48,6 +48,14 @@ class OcrPackagingHelper extends OcrHelper { String getActionExtractText(final AppLocalizations appLocalizations) => appLocalizations.edit_packaging_extract_btn_text; + @override + String getActionExtractingData(AppLocalizations appLocalizations) => + appLocalizations.edit_packaging_extracting_btn_text; + + @override + String getActionLoadingPhoto(AppLocalizations appLocalizations) => + appLocalizations.edit_packaging_loading_photo_btn_text; + @override String getActionRefreshPhoto(final AppLocalizations appLocalizations) => appLocalizations.edit_packaging_refresh_photo_btn_text; From f963dbcd43abba4edf3c8016f711d7cad2fdba34 Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Mon, 17 Jun 2024 19:08:33 +0200 Subject: [PATCH 19/85] ci: labeler OCR (#5397) --- .github/labeler.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index be330d5dbcc..4fca91ccd05 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -247,6 +247,13 @@ Product scan carousel: - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/edit_new_packagings.dart' - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart' +OCR page: +- changed-files: + - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart' + - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart' + - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart' + - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart' + ✏️ Editing - Basic info input: - changed-files: - any-glob-to-any-file: 'packages/smooth_app/lib/pages/product/add_basic_details_page.dart' From 8a415f8a19037a314a66a447960ee0453c4a37ec Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 18 Jun 2024 12:15:51 +0200 Subject: [PATCH 20/85] OCR page: missing case fixed + file splitted (#5395) --- .../edit_ocr/edit_ocr_main_action.dart | 209 ++++++++++++++++ .../product/{ => edit_ocr}/edit_ocr_page.dart | 229 +----------------- .../product/{ => edit_ocr}/ocr_helper.dart | 0 .../ocr_ingredients_helper.dart | 2 +- .../{ => edit_ocr}/ocr_packaging_helper.dart | 2 +- .../pages/product/product_field_editor.dart | 8 +- 6 files changed, 227 insertions(+), 223 deletions(-) create mode 100644 packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart rename packages/smooth_app/lib/pages/product/{ => edit_ocr}/edit_ocr_page.dart (69%) rename packages/smooth_app/lib/pages/product/{ => edit_ocr}/ocr_helper.dart (100%) rename packages/smooth_app/lib/pages/product/{ => edit_ocr}/ocr_ingredients_helper.dart (97%) rename packages/smooth_app/lib/pages/product/{ => edit_ocr}/ocr_packaging_helper.dart (97%) diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart new file mode 100644 index 00000000000..3cf5930fce8 --- /dev/null +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart @@ -0,0 +1,209 @@ +part of 'edit_ocr_page.dart'; + +class _EditOcrMainAction extends StatelessWidget { + const _EditOcrMainAction({ + required this.onPressed, + required this.helper, + required this.state, + }); + + final VoidCallback onPressed; + final OcrHelper helper; + final _OcrState state; + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + + final Widget? child = switch (state) { + _OcrState.IMAGE_LOADING => _EditOcrActionLoadingContent( + helper: helper, + appLocalizations: appLocalizations, + ), + _OcrState.IMAGE_LOADED => _ExtractMainActionContentLoaded( + helper: helper, + appLocalizations: appLocalizations, + onPressed: onPressed, + ), + _OcrState.EXTRACTING_DATA => _EditOcrActionExtractingContent( + helper: helper, + appLocalizations: appLocalizations, + ), + _OcrState.OTHER => null, + }; + + if (child == null) { + return EMPTY_WIDGET; + } + + final SmoothColorsThemeExtension theme = + Theme.of(context).extension()!; + + return SizedBox( + height: 45.0 * (_computeFontScaleFactor(context)), + width: double.infinity, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: ANGULAR_BORDER_RADIUS, + color: theme.primarySemiDark, + border: Border.all( + color: theme.primaryBlack, + width: 2.0, + ), + ), + child: Material( + type: MaterialType.transparency, + child: ProgressIndicatorTheme( + data: const ProgressIndicatorThemeData( + color: Colors.white, + ), + child: IconTheme( + data: const IconThemeData(color: Colors.white), + child: DefaultTextStyle( + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15.5, + color: Colors.white, + ), + child: child, + ), + ), + ), + ), + ), + ); + } + + double _computeFontScaleFactor(BuildContext context) { + final double fontSize = DefaultTextStyle.of(context).style.fontSize ?? 15.0; + final double scaledFontSize = + MediaQuery.textScalerOf(context).scale(fontSize); + + return scaledFontSize / fontSize; + } +} + +class _EditOcrActionExtractingContent extends StatelessWidget { + const _EditOcrActionExtractingContent({ + required this.helper, + required this.appLocalizations, + }); + + final OcrHelper helper; + final AppLocalizations appLocalizations; + + @override + Widget build(BuildContext context) { + return Semantics( + label: helper.getActionLoadingPhoto(appLocalizations), + excludeSemantics: true, + child: Shimmer( + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Colors.black, + Colors.white, + Colors.black, + ], + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const CircularProgressIndicator.adaptive(), + Expanded( + child: Text( + helper.getActionExtractingData(appLocalizations), + textAlign: TextAlign.center, + ), + ), + const CircularProgressIndicator.adaptive(), + ], + ), + ), + ), + ); + } +} + +class _ExtractMainActionContentLoaded extends StatelessWidget { + const _ExtractMainActionContentLoaded({ + required this.helper, + required this.appLocalizations, + required this.onPressed, + }); + + final OcrHelper helper; + final AppLocalizations appLocalizations; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return Semantics( + excludeSemantics: true, + value: helper.getActionExtractText(appLocalizations), + button: true, + child: InkWell( + onTap: onPressed, + borderRadius: ANGULAR_BORDER_RADIUS, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Text( + helper.getActionExtractText(appLocalizations), + ), + ), + const Icon( + Icons.download, + semanticLabel: '', + ), + ], + ), + ), + ), + ); + } +} + +class _EditOcrActionLoadingContent extends StatelessWidget { + const _EditOcrActionLoadingContent({ + required this.helper, + required this.appLocalizations, + }); + + final OcrHelper helper; + final AppLocalizations appLocalizations; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Text( + helper.getActionLoadingPhoto(appLocalizations), + ), + ), + const CircularProgressIndicator.adaptive(), + ], + ), + ); + } +} + +enum _OcrState { + IMAGE_LOADING, + IMAGE_LOADED, + EXTRACTING_DATA, + OTHER, +} diff --git a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart similarity index 69% rename from packages/smooth_app/lib/pages/product/edit_ocr_page.dart rename to packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index d9d48af0e93..f8862431125 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -15,13 +15,15 @@ import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/image_crop_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; +import 'package:smooth_app/pages/product/edit_ocr/ocr_helper.dart'; import 'package:smooth_app/pages/product/explanation_widget.dart'; import 'package:smooth_app/pages/product/multilingual_helper.dart'; -import 'package:smooth_app/pages/product/ocr_helper.dart'; import 'package:smooth_app/pages/product/product_image_button.dart'; import 'package:smooth_app/themes/smooth_theme_colors.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; +part 'edit_ocr_main_action.dart'; + /// Editing with OCR a product field and the corresponding image. /// /// Typical use-cases: ingredients and packaging. @@ -76,8 +78,6 @@ class _EditOcrPageState extends State with UpToDateMixin { return; } - setState(() => _extractingData = false); - if (extractedText == null || extractedText.isEmpty) { await LoadingDialog.error( context: context, @@ -89,7 +89,10 @@ class _EditOcrPageState extends State with UpToDateMixin { if (_controller.text != extractedText) { setState(() => _controller.text = extractedText); } - } catch (_) {} + } catch (_) { + } finally { + setState(() => _extractingData = false); + } } /// Updates the product field on the server. @@ -376,223 +379,15 @@ class _EditOcrPageState extends State with UpToDateMixin { return result; } - OcrState _extractState(TransientFile transientFile) { + _OcrState _extractState(TransientFile transientFile) { if (_extractingData) { - return OcrState.EXTRACTING_DATA; + return _OcrState.EXTRACTING_DATA; } else if (transientFile.isServerImage()) { - return OcrState.IMAGE_LOADED; + return _OcrState.IMAGE_LOADED; } else if (transientFile.isImageAvailable()) { - return OcrState.IMAGE_LOADING; + return _OcrState.IMAGE_LOADING; } else { - return OcrState.OTHER; + return _OcrState.OTHER; } } } - -class _EditOcrMainAction extends StatelessWidget { - const _EditOcrMainAction({ - required this.onPressed, - required this.helper, - required this.state, - }); - - final VoidCallback onPressed; - final OcrHelper helper; - final OcrState state; - - @override - Widget build(BuildContext context) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - - final Widget? child = switch (state) { - OcrState.IMAGE_LOADING => _EditOcrActionLoadingContent( - helper: helper, - appLocalizations: appLocalizations, - ), - OcrState.IMAGE_LOADED => _ExtractMainActionContentLoaded( - helper: helper, - appLocalizations: appLocalizations, - onPressed: onPressed, - ), - OcrState.EXTRACTING_DATA => _EditOcrActionExtractingContent( - helper: helper, - appLocalizations: appLocalizations, - ), - OcrState.OTHER => null, - }; - - if (child == null) { - return EMPTY_WIDGET; - } - - final SmoothColorsThemeExtension theme = - Theme.of(context).extension()!; - - return SizedBox( - height: 45.0 * (_computeFontScaleFactor(context)), - width: double.infinity, - child: DecoratedBox( - decoration: BoxDecoration( - borderRadius: ANGULAR_BORDER_RADIUS, - color: theme.primarySemiDark, - border: Border.all( - color: theme.primaryBlack, - width: 2.0, - ), - ), - child: Material( - type: MaterialType.transparency, - child: ProgressIndicatorTheme( - data: const ProgressIndicatorThemeData( - color: Colors.white, - ), - child: IconTheme( - data: const IconThemeData(color: Colors.white), - child: DefaultTextStyle( - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 15.5, - color: Colors.white, - ), - child: child, - ), - ), - ), - ), - ), - ); - } - - double _computeFontScaleFactor(BuildContext context) { - final double fontSize = DefaultTextStyle.of(context).style.fontSize ?? 15.0; - final double scaledFontSize = - MediaQuery.textScalerOf(context).scale(fontSize); - - return scaledFontSize / fontSize; - } -} - -class _EditOcrActionExtractingContent extends StatelessWidget { - const _EditOcrActionExtractingContent({ - required this.helper, - required this.appLocalizations, - }); - - final OcrHelper helper; - final AppLocalizations appLocalizations; - - @override - Widget build(BuildContext context) { - return Semantics( - label: helper.getActionLoadingPhoto(appLocalizations), - excludeSemantics: true, - child: Shimmer( - gradient: const LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: [ - Colors.black, - Colors.white, - Colors.black, - ], - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const CircularProgressIndicator.adaptive(), - Expanded( - child: Text( - helper.getActionExtractingData(appLocalizations), - textAlign: TextAlign.center, - ), - ), - const CircularProgressIndicator.adaptive(), - ], - ), - ), - ), - ); - } -} - -class _ExtractMainActionContentLoaded extends StatelessWidget { - const _ExtractMainActionContentLoaded({ - required this.helper, - required this.appLocalizations, - required this.onPressed, - }); - - final OcrHelper helper; - final AppLocalizations appLocalizations; - final VoidCallback onPressed; - - @override - Widget build(BuildContext context) { - return Semantics( - excludeSemantics: true, - value: helper.getActionExtractText(appLocalizations), - button: true, - child: InkWell( - onTap: onPressed, - borderRadius: ANGULAR_BORDER_RADIUS, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Text( - helper.getActionExtractText(appLocalizations), - ), - ), - const Icon( - Icons.download, - semanticLabel: '', - ), - ], - ), - ), - ), - ); - } -} - -class _EditOcrActionLoadingContent extends StatelessWidget { - const _EditOcrActionLoadingContent({ - required this.helper, - required this.appLocalizations, - }); - - final OcrHelper helper; - final AppLocalizations appLocalizations; - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Text( - helper.getActionLoadingPhoto(appLocalizations), - ), - ), - const CircularProgressIndicator.adaptive(), - ], - ), - ); - } -} - -enum OcrState { - IMAGE_LOADING, - IMAGE_LOADED, - EXTRACTING_DATA, - OTHER, -} diff --git a/packages/smooth_app/lib/pages/product/ocr_helper.dart b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_helper.dart similarity index 100% rename from packages/smooth_app/lib/pages/product/ocr_helper.dart rename to packages/smooth_app/lib/pages/product/edit_ocr/ocr_helper.dart diff --git a/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart similarity index 97% rename from packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart rename to packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart index 1421d5a70d8..a721059e75a 100644 --- a/packages/smooth_app/lib/pages/product/ocr_ingredients_helper.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart @@ -2,7 +2,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/background/background_task_details.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; -import 'package:smooth_app/pages/product/ocr_helper.dart'; +import 'package:smooth_app/pages/product/edit_ocr/ocr_helper.dart'; import 'package:smooth_app/query/product_query.dart'; /// OCR Helper for ingredients. diff --git a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart similarity index 97% rename from packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart rename to packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart index 600e24a7563..a22d6f94350 100644 --- a/packages/smooth_app/lib/pages/product/ocr_packaging_helper.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart @@ -4,7 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/background/background_task_details.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; -import 'package:smooth_app/pages/product/ocr_helper.dart'; +import 'package:smooth_app/pages/product/edit_ocr/ocr_helper.dart'; import 'package:smooth_app/query/product_query.dart'; /// OCR Helper for packaging. diff --git a/packages/smooth_app/lib/pages/product/product_field_editor.dart b/packages/smooth_app/lib/pages/product/product_field_editor.dart index 6c4f415b926..55b7c4717e4 100644 --- a/packages/smooth_app/lib/pages/product/product_field_editor.dart +++ b/packages/smooth_app/lib/pages/product/product_field_editor.dart @@ -5,11 +5,11 @@ import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/pages/product/add_basic_details_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/edit_new_packagings.dart'; -import 'package:smooth_app/pages/product/edit_ocr_page.dart'; +import 'package:smooth_app/pages/product/edit_ocr/edit_ocr_page.dart'; +import 'package:smooth_app/pages/product/edit_ocr/ocr_helper.dart'; +import 'package:smooth_app/pages/product/edit_ocr/ocr_ingredients_helper.dart'; +import 'package:smooth_app/pages/product/edit_ocr/ocr_packaging_helper.dart'; import 'package:smooth_app/pages/product/nutrition_page_loaded.dart'; -import 'package:smooth_app/pages/product/ocr_helper.dart'; -import 'package:smooth_app/pages/product/ocr_ingredients_helper.dart'; -import 'package:smooth_app/pages/product/ocr_packaging_helper.dart'; import 'package:smooth_app/pages/product/simple_input_page.dart'; import 'package:smooth_app/pages/product/simple_input_page_helpers.dart'; From 229ea667f7b2e725506b150d605376de45197fb8 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 18 Jun 2024 12:26:10 +0200 Subject: [PATCH 21/85] Tagline: support for countries only locales: (eg `_FR`) (#5370) --- .../lib/data_models/news_feed/newsfeed_json.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart index 9ddd6e2a7ab..e10b4be3901 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart @@ -96,9 +96,13 @@ class _TagLineItemNewsItem { if (_translations.containsKey(locale)) { translation = _translations[locale]; } else if (locale.contains('_')) { - final String languageCode = locale.split('_').first; + final List splittedLocale = locale.split('_'); + final String languageCode = splittedLocale.first; + final String countryCode = '_${splittedLocale.last}'; if (_translations.containsKey(languageCode)) { translation = _translations[languageCode]; + } else if (_translations.containsKey(countryCode)) { + translation = _translations[countryCode]; } } @@ -335,9 +339,13 @@ class _TaglineJSONFeed { // Try by language if (locale.contains('_')) { - final String languageCode = locale.split('_').first; + final List splittedLocale = locale.split('_'); + final String languageCode = splittedLocale.first; + final String countryCode = '_${splittedLocale.last}'; if (_news.containsKey(languageCode)) { return _news[languageCode]!; + } else if (_news.containsKey(countryCode)) { + return _news[countryCode]!; } } From 64d38f17dafb715499857fc4611bb3f25cdbb524 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 18 Jun 2024 13:42:39 +0200 Subject: [PATCH 22/85] feat: Improve photo gallery accessibility + internationalization (#5366) * Photo gallery: accessibility improvements + date format translatable * Fix typos * Use `DateFormat.ymd` instead * Card based layout --- packages/smooth_app/lib/l10n/app_en.arb | 18 +++ .../product_image_gallery_other_view.dart | 32 +++-- .../lib/pages/image/product_image_widget.dart | 131 +++++++++++++----- 3 files changed, 137 insertions(+), 44 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 365f0483080..6cd64568fcf 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" diff --git a/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart b/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart index 677a5506017..3f40df632f7 100644 --- a/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart +++ b/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart @@ -4,6 +4,7 @@ import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/fetched_product.dart'; import 'package:smooth_app/database/local_database.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/image/product_image_other_page.dart'; import 'package:smooth_app/pages/image/product_image_widget.dart'; @@ -116,20 +117,27 @@ class _RawGridGallery extends StatelessWidget { // order by descending ids index = rawImages.length - 1 - index; final ProductImage productImage = rawImages[index]; - return InkWell( - onTap: () async => Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => ProductImageOtherPage( - product, - int.parse(productImage.imgid!), + return Padding( + padding: EdgeInsetsDirectional.only( + start: VERY_SMALL_SPACE, + end: index % _columns == 0 ? VERY_SMALL_SPACE : 0.0, + bottom: VERY_SMALL_SPACE, + ), + child: InkWell( + onTap: () async => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => ProductImageOtherPage( + product, + int.parse(productImage.imgid!), + ), ), ), - ), - child: ProductImageWidget( - productImage: productImage, - barcode: product.barcode!, - squareSize: squareSize, + child: ProductImageWidget( + productImage: productImage, + barcode: product.barcode!, + squareSize: squareSize, + ), ), ); }, diff --git a/packages/smooth_app/lib/pages/image/product_image_widget.dart b/packages/smooth_app/lib/pages/image/product_image_widget.dart index 9774a555b7b..c1448413b52 100644 --- a/packages/smooth_app/lib/pages/image/product_image_widget.dart +++ b/packages/smooth_app/lib/pages/image/product_image_widget.dart @@ -1,13 +1,17 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/resources/app_icons.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; /// Displays a product image thumbnail with the upload date on top. -class ProductImageWidget extends StatelessWidget { +class ProductImageWidget extends StatefulWidget { const ProductImageWidget({ required this.productImage, required this.barcode, @@ -18,54 +22,117 @@ class ProductImageWidget extends StatelessWidget { final String barcode; final double squareSize; - static final DateFormat _dateFormat = DateFormat('yyyy-MM-dd'); + @override + State createState() => _ProductImageWidgetState(); +} + +class _ProductImageWidgetState extends State { + @override + void initState() { + super.initState(); + _loadImagePalette(); + } + + Future _loadImagePalette() async { + final ColorScheme palette = await ColorScheme.fromImageProvider( + provider: NetworkImage(widget.productImage.getUrl( + widget.barcode, + uriHelper: ProductQuery.uriProductHelper, + ))); + + setState(() { + backgroundColor = palette.primaryContainer; + darkBackground = backgroundColor!.computeLuminance() < 0.5; + }); + } + + Color? backgroundColor; + bool? darkBackground; @override Widget build(BuildContext context) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final DateFormat dateFormat = + DateFormat.yMd(ProductQuery.getLanguage().offTag); + + darkBackground = darkBackground ?? true; + final Widget image = SmoothImage( - width: squareSize, - height: squareSize, + width: widget.squareSize, + height: widget.squareSize, imageProvider: NetworkImage( - productImage.getUrl( - barcode, + widget.productImage.getUrl( + widget.barcode, uriHelper: ProductQuery.uriProductHelper, ), ), rounded: false, ); - final DateTime? uploaded = productImage.uploaded; + final DateTime? uploaded = widget.productImage.uploaded; if (uploaded == null) { return image; } - final DateTime now = DateTime.now(); - final String date = _dateFormat.format(uploaded); - final bool expired = now.difference(uploaded).inDays > 365; - return Stack( - children: [ - image, - SizedBox( - width: squareSize, - height: squareSize, - child: Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(SMALL_SPACE), - child: Container( - height: VERY_LARGE_SPACE, - color: expired - ? Colors.red.withAlpha(128) - : Colors.white.withAlpha(128), - child: Center( - child: AutoSizeText( - date, - maxLines: 1, + final bool expired = DateTime.now().difference(uploaded).inDays > 365; + final String date = dateFormat.format(uploaded); + + return Semantics( + label: expired + ? appLocalizations.product_image_outdated_accessibility_label(date) + : appLocalizations.product_image_accessibility_label(date), + excludeSemantics: true, + button: true, + child: SmoothCard( + padding: EdgeInsets.zero, + color: backgroundColor ?? colors.primaryBlack, + borderRadius: ANGULAR_BORDER_RADIUS, + margin: EdgeInsets.zero, + child: ClipRRect( + borderRadius: ANGULAR_BORDER_RADIUS, + child: Column( + children: [ + Expanded( + child: image, + ), + SizedBox( + width: double.infinity, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: SMALL_SPACE, + vertical: VERY_SMALL_SPACE, + ), + child: Stack( + children: [ + Center( + child: AutoSizeText( + date, + maxLines: 1, + style: TextStyle( + color: darkBackground! + ? Colors.white + : colors.primaryDark, + ), + ), + ), + if (expired) + Positioned.directional( + end: 0.0, + height: 20.0, + textDirection: Directionality.of(context), + child: Outdated( + size: 18.0, + color: colors.red, + ), + ), + ], ), ), - ), - ), + ) + ], ), ), - ], + ), ); } } From 4b4f387c01235d097cbb285fdc67a6abfb04f109 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 18 Jun 2024 15:54:52 +0200 Subject: [PATCH 23/85] Hide the NutriScore V2 guide in France (#5399) --- .../preferences/user_preferences_faq.dart | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart index 53a523f6999..7263e39e9e2 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart @@ -65,24 +65,25 @@ class UserPreferencesFaq extends AbstractUserPreferences { false, ), ), - _getListTile( - title: appLocalizations.faq_nutriscore_nutriscore, - leadingSvg: SvgCache.getAssetsCacheForNutriscore( - NutriScoreValue.b, - true, - ), - onTap: () => Navigator.of(context, rootNavigator: true).push( - MaterialPageRoute( - builder: (BuildContext context) => const GuideNutriscoreV2(), + if (userPreferences.userCountryCode != 'fr') + _getListTile( + title: appLocalizations.faq_nutriscore_nutriscore, + leadingSvg: SvgCache.getAssetsCacheForNutriscore( + NutriScoreValue.b, + true, + ), + onTap: () => Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute( + builder: (BuildContext context) => const GuideNutriscoreV2(), + ), ), - ), - /// Hide the icon - icon: const Icon( - Icons.info, - size: 0.0, + /// Hide the icon + icon: const Icon( + Icons.info, + size: 0.0, + ), ), - ), _getNutriListTile( title: appLocalizations.ecoscore_generic, url: 'https://world.openfoodfacts.org/ecoscore', From b9f83c414073e5a0c42b86f3226d6e2ee3c50bad Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Tue, 18 Jun 2024 15:55:05 +0200 Subject: [PATCH 24/85] feat: 5203 - "add receipt" and "add price tags", even offline or not found (#5392) Impacted files: * `app_en.arb`: added 2 "add" and 4 "price product" labels * `app_fr.arb`: added 2 "add" and 4 "price product" labels * `edit_product_page.dart`: minor refactoring * `get_prices_model.dart`: minor refactoring * `price_amount_card.dart`: added the case of "no product yet" * `price_amount_model.dart`: added "no product yet" check * `price_meta_product.dart`: 2 more cases - "no product yet" and "not found product" * `price_product_list_tile.dart`: minor refactoring * `price_product_search_page.dart`: now we accept "not found" products and we don't force the server lookup * `prices_card.dart`: minor refactoring * `product_price_add_page.dart`: minor refactoring * `user_preferences_account.dart`: added "Add receipt" and "Add price tags" --- packages/smooth_app/lib/l10n/app_en.arb | 6 ++ packages/smooth_app/lib/l10n/app_fr.arb | 6 ++ .../preferences/user_preferences_account.dart | 20 +++++ .../lib/pages/prices/get_prices_model.dart | 1 + .../lib/pages/prices/price_amount_card.dart | 36 ++++++-- .../lib/pages/prices/price_amount_model.dart | 6 +- .../lib/pages/prices/price_meta_product.dart | 84 +++++++++++++++---- .../pages/prices/price_product_list_tile.dart | 16 +--- .../prices/price_product_search_page.dart | 31 ++++++- .../lib/pages/prices/prices_card.dart | 1 + .../pages/prices/product_price_add_page.dart | 7 +- .../lib/pages/product/edit_product_page.dart | 1 + 12 files changed, 174 insertions(+), 41 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 6cd64568fcf..f966f3943b4 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1710,6 +1710,11 @@ "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", "prices_barcode_search_title": "Product search", "prices_barcode_search_running": "Looking for {barcode}", "@prices_barcode_search_running": { @@ -1781,6 +1786,7 @@ "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 81c01ace21f..92aa57cbeea 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -1678,6 +1678,11 @@ "prices_send_n_prices": "{count,plural, =1{Envoyer le prix} other{Envoyer {count} prix}}", "prices_add_an_item": "Ajouter un article", "prices_add_a_price": "Ajouter un prix", + "prices_add_a_receipt": "Ajouter un ticket de caisse", + "prices_add_price_tags": "Ajouter des étiquettes de prix", + "prices_barcode_search_not_found": "Produit non trouvé", + "prices_barcode_search_none_yet": "Pas encore de produit", + "prices_barcode_search_question": "Voulez-vous chercher ce produit ?", "prices_barcode_search_title": "Recherche de produit", "prices_barcode_search_running": "À la recherche de {barcode}", "@prices_barcode_search_running": { @@ -1749,6 +1754,7 @@ "prices_amount_price_normal": "Prix", "prices_amount_price_discounted": "Prix en promo", "prices_amount_price_not_discounted": "Prix d'origine", + "prices_amount_no_product": "Il manque un produit !", "prices_amount_price_incorrect": "Valeur incorrecte", "prices_amount_price_mandatory": "Valeur obligatoire", "prices_currency_subtitle": "Devise", diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart index 8104857b724..94ad1b57cb3 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart @@ -18,10 +18,12 @@ import 'package:smooth_app/pages/preferences/user_preferences_item.dart'; import 'package:smooth_app/pages/preferences/user_preferences_list_tile.dart'; import 'package:smooth_app/pages/preferences/user_preferences_page.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/price_user_button.dart'; import 'package:smooth_app/pages/prices/prices_page.dart'; import 'package:smooth_app/pages/prices/prices_proofs_page.dart'; import 'package:smooth_app/pages/prices/prices_users_page.dart'; +import 'package:smooth_app/pages/prices/product_price_add_page.dart'; import 'package:smooth_app/pages/product/common/product_query_page_helper.dart'; import 'package:smooth_app/pages/user_management/login_page.dart'; import 'package:smooth_app/query/paged_product_query.dart'; @@ -237,6 +239,24 @@ class UserPreferencesAccount extends AbstractUserPreferences { ), Icons.receipt, ), + _getListTile( + appLocalizations.prices_add_a_receipt, + () async => ProductPriceAddPage.showProductPage( + context: context, + product: PriceMetaProduct.empty(), + proofType: ProofType.receipt, + ), + Icons.add_shopping_cart, + ), + _getListTile( + appLocalizations.prices_add_price_tags, + () async => ProductPriceAddPage.showProductPage( + context: context, + product: PriceMetaProduct.empty(), + proofType: ProofType.priceTag, + ), + Icons.add_shopping_cart, + ), _getListTile( appLocalizations.all_search_prices_latest_title, () async => Navigator.of(context).push( diff --git a/packages/smooth_app/lib/pages/prices/get_prices_model.dart b/packages/smooth_app/lib/pages/prices/get_prices_model.dart index 726b2fee50e..2087975356d 100644 --- a/packages/smooth_app/lib/pages/prices/get_prices_model.dart +++ b/packages/smooth_app/lib/pages/prices/get_prices_model.dart @@ -33,6 +33,7 @@ class GetPricesModel { addButton: () async => ProductPriceAddPage.showProductPage( context: context, product: product, + proofType: ProofType.priceTag, ), enableCountButton: false, ); diff --git a/packages/smooth_app/lib/pages/prices/price_amount_card.dart b/packages/smooth_app/lib/pages/prices/price_amount_card.dart index f5eb0b1d089..314c5209045 100644 --- a/packages/smooth_app/lib/pages/prices/price_amount_card.dart +++ b/packages/smooth_app/lib/pages/prices/price_amount_card.dart @@ -5,8 +5,10 @@ import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; import 'package:smooth_app/pages/prices/price_amount_field.dart'; import 'package:smooth_app/pages/prices/price_amount_model.dart'; +import 'package:smooth_app/pages/prices/price_meta_product.dart'; import 'package:smooth_app/pages/prices/price_model.dart'; import 'package:smooth_app/pages/prices/price_product_list_tile.dart'; +import 'package:smooth_app/pages/prices/price_product_search_page.dart'; /// Card that displays the amounts (discounted or not) for price adding. class PriceAmountCard extends StatefulWidget { @@ -36,6 +38,7 @@ class _PriceAmountCardState extends State { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); + final bool isEmpty = widget.model.product.barcode.isEmpty; return SmoothCard( child: Column( children: [ @@ -45,13 +48,32 @@ class _PriceAmountCardState extends State { ), PriceProductListTile( product: widget.model.product, - trailingIconData: widget.total == 1 ? null : Icons.clear, - onPressed: widget.total == 1 - ? null - : () { - widget.priceModel.priceAmountModels.removeAt(widget.index); - widget.refresh.call(); - }, + trailingIconData: isEmpty + ? Icons.edit + : widget.total == 1 + ? null + : Icons.clear, + onPressed: isEmpty + ? () async { + final PriceMetaProduct? product = + await Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => + const PriceProductSearchPage(), + ), + ); + if (product == null) { + return; + } + setState(() => widget.model.product = product); + } + : widget.total == 1 + ? null + : () { + widget.priceModel.priceAmountModels + .removeAt(widget.index); + widget.refresh.call(); + }, ), SmoothLargeButtonWithIcon( icon: widget.model.promo diff --git a/packages/smooth_app/lib/pages/prices/price_amount_model.dart b/packages/smooth_app/lib/pages/prices/price_amount_model.dart index 32ec3d100ef..d635342fb33 100644 --- a/packages/smooth_app/lib/pages/prices/price_amount_model.dart +++ b/packages/smooth_app/lib/pages/prices/price_amount_model.dart @@ -33,13 +33,17 @@ class PriceAmountModel { ); String? checkParameters(final BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + if (product.barcode.isEmpty) { + return appLocalizations.prices_amount_no_product; + } _checkedPaidPrice = validateDouble(_paidPrice)!; _checkedPriceWithoutDiscount = null; if (promo) { if (_priceWithoutDiscount.isNotEmpty) { _checkedPriceWithoutDiscount = validateDouble(_priceWithoutDiscount); if (_checkedPriceWithoutDiscount == null) { - return AppLocalizations.of(context).prices_amount_price_incorrect; + return appLocalizations.prices_amount_price_incorrect; } } } diff --git a/packages/smooth_app/lib/pages/prices/price_meta_product.dart b/packages/smooth_app/lib/pages/prices/price_meta_product.dart index 31af34fed44..cfda26b292e 100644 --- a/packages/smooth_app/lib/pages/prices/price_meta_product.dart +++ b/packages/smooth_app/lib/pages/prices/price_meta_product.dart @@ -1,25 +1,81 @@ +import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; +import 'package:smooth_app/generic_lib/widgets/smooth_product_image.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; /// Meta version of a product, coming from OFF or from Prices. class PriceMetaProduct { - PriceMetaProduct.product(Product this.product) : priceProduct = null; - PriceMetaProduct.priceProduct(PriceProduct this.priceProduct) - : product = null; + PriceMetaProduct.product(final Product product) + : _product = product, + _priceProduct = null, + _barcode = null; + PriceMetaProduct.priceProduct(final PriceProduct priceProduct) + : _product = null, + _priceProduct = priceProduct, + _barcode = null; + PriceMetaProduct.empty() + : _product = null, + _priceProduct = null, + _barcode = null; + PriceMetaProduct.unknown(final String barcode) + : _product = null, + _priceProduct = null, + _barcode = barcode; - final Product? product; - final PriceProduct? priceProduct; + final Product? _product; + final PriceProduct? _priceProduct; + final String? _barcode; - String get barcode => - product != null ? product!.barcode! : priceProduct!.code; + // TODO(monsieurtanuki): refine this test + bool get isValid => barcode.length >= 8; - String getName(final AppLocalizations appLocalizations) => product != null - ? getProductNameAndBrands( - product!, - appLocalizations, - ) - : priceProduct!.name ?? priceProduct!.code; + String get barcode { + if (_product != null) { + return _product.barcode!; + } + if (_priceProduct != null) { + return _priceProduct.code; + } + return _barcode ?? ''; + } - String? get imageUrl => product != null ? null : priceProduct!.imageURL; + String getName(final AppLocalizations appLocalizations) { + if (_product != null) { + return getProductNameAndBrands( + _product, + appLocalizations, + ); + } + if (_priceProduct != null) { + return _priceProduct.name ?? _priceProduct.code; + } + if (barcode.isEmpty) { + return appLocalizations.prices_barcode_search_none_yet; + } + return appLocalizations.prices_barcode_search_not_found; + } + + Widget getImageWidget(final double size) { + if (_product != null) { + return SmoothMainProductImage( + product: _product, + width: size, + height: size, + ); + } + if (_priceProduct != null) { + final String? imageURL = _priceProduct.imageURL; + return SmoothImage( + width: size, + height: size, + imageProvider: imageURL == null ? null : NetworkImage(imageURL), + ); + } + return SmoothImage( + width: size, + height: size, + ); + } } diff --git a/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart b/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart index 31cb5f3a0ff..ef3b38d0a30 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_list_tile.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_product_image.dart'; import 'package:smooth_app/pages/prices/price_meta_product.dart'; /// Displays a meta product with an action button, as a ListTile. @@ -28,19 +26,7 @@ class PriceProductListTile extends StatelessWidget { children: [ SizedBox( width: size, - child: product.product != null - ? SmoothMainProductImage( - product: product.product!, - width: size, - height: size, - ) - : SmoothImage( - width: size, - height: size, - imageProvider: product.imageUrl == null - ? null - : NetworkImage(product.imageUrl!), - ), + child: product.getImageWidget(size), ), const SizedBox(width: SMALL_SPACE), Expanded( diff --git a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart index 74a4933cb59..e16b639b764 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart @@ -7,6 +7,7 @@ import 'package:smooth_app/data_models/fetched_product.dart'; import 'package:smooth_app/database/dao_product.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/generic_lib/loading_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; @@ -50,6 +51,8 @@ class _PriceProductSearchPageState extends State { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); + final PriceMetaProduct priceMetaProduct = + _product ?? PriceMetaProduct.unknown(_controller.text); // TODO(monsieurtanuki): add WillPopScope2 return SmoothScaffold( appBar: SmoothAppBar( @@ -80,13 +83,13 @@ class _PriceProductSearchPageState extends State { prefixIcon: const Icon(CupertinoIcons.barcode), textInputAction: TextInputAction.search, ), - if (_product != null) + if (priceMetaProduct.isValid) Padding( padding: const EdgeInsets.symmetric(vertical: LARGE_SPACE), child: PriceProductListTile( - product: _product!, + product: priceMetaProduct, trailingIconData: Icons.check_circle, - onPressed: () => Navigator.of(context).pop(_product), + onPressed: () => Navigator.of(context).pop(priceMetaProduct), ), ), ], @@ -167,6 +170,7 @@ class _PriceProductSearchPageState extends State { setState(() => _product = PriceMetaProduct.product(product)); return; } + setState(() {}); } Future _onFieldSubmitted(final BuildContext context) async { @@ -187,6 +191,7 @@ class _PriceProductSearchPageState extends State { } Future _scan(final BuildContext context) async { + final AppLocalizations appLocalizations = AppLocalizations.of(context); final String? barcode = await Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => const PriceScanPage(), @@ -206,6 +211,26 @@ class _PriceProductSearchPageState extends State { if (!context.mounted) { return; } + final bool? accepts = await showDialog( + context: context, + builder: (final BuildContext context) => SmoothAlertDialog( + body: Text(appLocalizations.prices_barcode_search_question), + neutralAction: SmoothActionButton( + text: appLocalizations.cancel, + onPressed: () => Navigator.of(context).pop(false), + ), + positiveAction: SmoothActionButton( + text: appLocalizations.yes, + onPressed: () => Navigator.of(context).pop(true), + ), + ), + ); + if (!context.mounted) { + return; + } + if (accepts != true) { + return; + } await _onFieldSubmitted(context); } } diff --git a/packages/smooth_app/lib/pages/prices/prices_card.dart b/packages/smooth_app/lib/pages/prices/prices_card.dart index 3a5f9acdbe6..f4475c1e5d7 100644 --- a/packages/smooth_app/lib/pages/prices/prices_card.dart +++ b/packages/smooth_app/lib/pages/prices/prices_card.dart @@ -96,6 +96,7 @@ class PricesCard extends StatelessWidget { onPressed: () async => ProductPriceAddPage.showProductPage( context: context, product: PriceMetaProduct.product(product), + proofType: ProofType.priceTag, ), ), ), diff --git a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart index d66d765db05..d851750fc1f 100644 --- a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart +++ b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart @@ -29,14 +29,17 @@ class ProductPriceAddPage extends StatefulWidget { const ProductPriceAddPage({ required this.product, required this.latestOsmLocations, + required this.proofType, }); final PriceMetaProduct product; final List latestOsmLocations; + final ProofType proofType; static Future showProductPage({ required final BuildContext context, required final PriceMetaProduct product, + required final ProofType proofType, }) async { if (!await ProductRefresher().checkIfLoggedIn( context, @@ -58,6 +61,7 @@ class ProductPriceAddPage extends StatefulWidget { builder: (BuildContext context) => ProductPriceAddPage( product: product, latestOsmLocations: osmLocations, + proofType: proofType, ), ), ); @@ -69,7 +73,7 @@ class ProductPriceAddPage extends StatefulWidget { class _ProductPriceAddPageState extends State { late final PriceModel _model = PriceModel( - proofType: ProofType.priceTag, + proofType: widget.proofType, locations: widget.latestOsmLocations, product: widget.product, ); @@ -118,6 +122,7 @@ class _ProductPriceAddPageState extends State { index: i, refresh: () => setState(() {}), ), + // TODO(monsieurtanuki): check if there's an empty barcode before displaying this card SmoothCard( child: SmoothLargeButtonWithIcon( text: appLocalizations.prices_add_an_item, diff --git a/packages/smooth_app/lib/pages/product/edit_product_page.dart b/packages/smooth_app/lib/pages/product/edit_product_page.dart index 610ae38ab5c..83d542fafc9 100644 --- a/packages/smooth_app/lib/pages/product/edit_product_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_product_page.dart @@ -263,6 +263,7 @@ class _EditProductPageState extends State with UpToDateMixin { onTap: () async => ProductPriceAddPage.showProductPage( context: context, product: PriceMetaProduct.product(upToDateProduct), + proofType: ProofType.priceTag, ), ), ], From 6026fbc91bdad67d84cdffd8c8cbefa1b15914aa Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Wed, 19 Jun 2024 10:07:31 +0200 Subject: [PATCH 25/85] fix: Fix issues with themes (#5410) * Fix issues with themes * Reformat code --- .../lib/data_models/preferences/user_preferences.dart | 4 +++- packages/smooth_app/lib/resources/app_animations.dart | 2 +- packages/smooth_app/lib/themes/theme_provider.dart | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart index a9496dfda1d..6bed2453a2d 100644 --- a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart +++ b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart @@ -7,6 +7,7 @@ import 'package:smooth_app/data_models/product_preferences.dart'; import 'package:smooth_app/pages/onboarding/onboarding_flow_navigator.dart'; import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/themes/color_schemes.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; part 'package:smooth_app/data_models/preferences/migration/user_preferences_migration.dart'; @@ -203,7 +204,8 @@ class UserPreferences extends ChangeNotifier { _sharedPreferences.getBool(_TAG_CRASH_REPORTS) ?? false; String get currentTheme => - _sharedPreferences.getString(_TAG_CURRENT_THEME_MODE) ?? 'System Default'; + _sharedPreferences.getString(_TAG_CURRENT_THEME_MODE) ?? + THEME_SYSTEM_DEFAULT; String get currentColor => _sharedPreferences.getString(_TAG_CURRENT_COLOR_SCHEME) ?? diff --git a/packages/smooth_app/lib/resources/app_animations.dart b/packages/smooth_app/lib/resources/app_animations.dart index 2b8a602ab10..1acdaaf48f1 100644 --- a/packages/smooth_app/lib/resources/app_animations.dart +++ b/packages/smooth_app/lib/resources/app_animations.dart @@ -169,7 +169,7 @@ class _SearchEyeAnimationState extends State { @override Widget build(BuildContext context) { final double size = widget.size ?? IconTheme.of(context).size ?? 24.0; - final bool lightTheme = context.watch().isDarkMode(context); + final bool lightTheme = !context.watch().isDarkMode(context); return ExcludeSemantics( child: SizedBox( diff --git a/packages/smooth_app/lib/themes/theme_provider.dart b/packages/smooth_app/lib/themes/theme_provider.dart index 0bb268f8d89..08862fb23ba 100644 --- a/packages/smooth_app/lib/themes/theme_provider.dart +++ b/packages/smooth_app/lib/themes/theme_provider.dart @@ -66,8 +66,10 @@ class ThemeProvider with ChangeNotifier { } bool isDarkMode(BuildContext context) { - return currentThemeMode != ThemeMode.light && - MediaQuery.platformBrightnessOf(context) == Brightness.dark; + if (currentTheme == THEME_SYSTEM_DEFAULT) { + return MediaQuery.platformBrightnessOf(context) == Brightness.dark; + } + return [THEME_DARK, THEME_AMOLED].contains(currentTheme); } @override From 60cafa59f085c547c30924b4c3330917d51dc8e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:53:27 +0200 Subject: [PATCH 26/85] chore(deps): bump fastlane in /packages/smooth_app/ios (#5406) Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.220.0 to 2.221.0. - [Release notes](https://github.com/fastlane/fastlane/releases) - [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md) - [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.220.0...fastlane/2.221.0) --- updated-dependencies: - dependency-name: fastlane dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/ios/Gemfile.lock | 32 +++++++++++++++------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/smooth_app/ios/Gemfile.lock b/packages/smooth_app/ios/Gemfile.lock index d039a2eb59a..a433dd13be8 100644 --- a/packages/smooth_app/ios/Gemfile.lock +++ b/packages/smooth_app/ios/Gemfile.lock @@ -16,17 +16,17 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.907.0) - aws-sdk-core (3.191.6) + aws-partitions (1.944.0) + aws-sdk-core (3.197.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.78.0) - aws-sdk-core (~> 3, >= 3.191.0) + aws-sdk-kms (1.85.0) + aws-sdk-core (~> 3, >= 3.197.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.146.1) - aws-sdk-core (~> 3, >= 3.191.0) + aws-sdk-s3 (1.152.3) + aws-sdk-core (~> 3, >= 3.197.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.8) aws-sigv4 (1.8.0) @@ -75,7 +75,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.220.0) + fastlane (2.221.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -156,31 +156,32 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.5) + http-cookie (1.0.6) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) json (2.7.2) - jwt (2.8.1) + jwt (2.8.2) base64 - mini_magick (4.12.0) + mini_magick (4.13.1) mini_mime (1.1.5) multi_json (1.15.0) - multipart-post (2.4.0) + multipart-post (2.4.1) nanaimo (0.3.0) naturally (2.2.1) nkf (0.2.0) - optparse (0.4.0) + optparse (0.5.0) os (1.1.4) plist (3.7.1) - public_suffix (5.0.5) - rake (13.2.0) + public_suffix (5.1.1) + rake (13.2.1) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.6) + rexml (3.2.9) + strscan rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) @@ -193,6 +194,7 @@ GEM simctl (1.6.10) CFPropertyList naturally + strscan (3.1.0) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) From 39b65d2085521b33a51124d7b5fed96857d8c0e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:53:42 +0200 Subject: [PATCH 27/85] chore(deps): bump fastlane in /packages/smooth_app/android (#5407) Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.220.0 to 2.221.0. - [Release notes](https://github.com/fastlane/fastlane/releases) - [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md) - [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.220.0...fastlane/2.221.0) --- updated-dependencies: - dependency-name: fastlane dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/android/Gemfile.lock | 32 +++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/smooth_app/android/Gemfile.lock b/packages/smooth_app/android/Gemfile.lock index f1f735f4275..08a141e586b 100644 --- a/packages/smooth_app/android/Gemfile.lock +++ b/packages/smooth_app/android/Gemfile.lock @@ -16,17 +16,17 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.907.0) - aws-sdk-core (3.191.6) + aws-partitions (1.944.0) + aws-sdk-core (3.197.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.78.0) - aws-sdk-core (~> 3, >= 3.191.0) + aws-sdk-kms (1.85.0) + aws-sdk-core (~> 3, >= 3.197.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.146.1) - aws-sdk-core (~> 3, >= 3.191.0) + aws-sdk-s3 (1.152.3) + aws-sdk-core (~> 3, >= 3.197.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.8) aws-sigv4 (1.8.0) @@ -74,7 +74,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.220.0) + fastlane (2.221.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -155,31 +155,32 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.5) + http-cookie (1.0.6) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) json (2.7.2) - jwt (2.8.1) + jwt (2.8.2) base64 - mini_magick (4.12.0) + mini_magick (4.13.1) mini_mime (1.1.5) multi_json (1.15.0) - multipart-post (2.4.0) + multipart-post (2.4.1) nanaimo (0.3.0) naturally (2.2.1) nkf (0.2.0) - optparse (0.4.0) + optparse (0.5.0) os (1.1.4) plist (3.7.1) - public_suffix (5.0.5) - rake (13.2.0) + public_suffix (5.1.1) + rake (13.2.1) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.6) + rexml (3.2.9) + strscan rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) @@ -192,6 +193,7 @@ GEM simctl (1.6.10) CFPropertyList naturally + strscan (3.1.0) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) From 93d460cc231b75e3af38900594e795e1464908db Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Wed, 19 Jun 2024 13:15:34 +0200 Subject: [PATCH 28/85] Improve accessibility on the homepage (#5412) --- .../scanner/shared/lib/src/scanner_visor.dart | 36 +++--- .../news_feed/newsfeed_provider.dart | 4 +- .../lib/helpers/strings_helper.dart | 42 ++++--- packages/smooth_app/lib/l10n/app_en.arb | 13 ++ .../lib/pages/scan/camera_scan_page.dart | 26 ++-- .../carousel/main_card/scan_main_card.dart | 119 +++++++++--------- .../scan/carousel/main_card/scan_tagline.dart | 51 ++++---- 7 files changed, 165 insertions(+), 126 deletions(-) diff --git a/packages/scanner/shared/lib/src/scanner_visor.dart b/packages/scanner/shared/lib/src/scanner_visor.dart index 3eb78bf710f..15ebb165c89 100644 --- a/packages/scanner/shared/lib/src/scanner_visor.dart +++ b/packages/scanner/shared/lib/src/scanner_visor.dart @@ -160,23 +160,27 @@ class VisorButton extends StatelessWidget { @override Widget build(BuildContext context) { - return Material( - type: MaterialType.transparency, - child: InkWell( - onTap: onTap, - borderRadius: const BorderRadius.all( - Radius.circular( - SmoothBarcodeScannerVisor.CORNER_PADDING, + return Semantics( + label: tooltip, + excludeSemantics: true, + child: Material( + type: MaterialType.transparency, + child: InkWell( + onTap: onTap, + borderRadius: const BorderRadius.all( + Radius.circular( + SmoothBarcodeScannerVisor.CORNER_PADDING, + ), ), - ), - child: Tooltip( - message: tooltip, - enableFeedback: true, - child: Padding( - padding: const EdgeInsets.all(12.0), - child: IconTheme( - data: const IconThemeData(color: Colors.white), - child: child, + child: Tooltip( + message: tooltip, + enableFeedback: true, + child: Padding( + padding: const EdgeInsets.all(12.0), + child: IconTheme( + data: const IconThemeData(color: Colors.white), + child: child, + ), ), ), ), diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart index f5b8e8619ab..5b4e157d0ee 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart @@ -192,9 +192,9 @@ final class AppNewsStateLoading extends AppNewsState { } class AppNewsStateLoaded extends AppNewsState { - const AppNewsStateLoaded(this.tagLineContent); + const AppNewsStateLoaded(this.content); - final AppNews tagLineContent; + final AppNews content; } class AppNewsStateError extends AppNewsState { diff --git a/packages/smooth_app/lib/helpers/strings_helper.dart b/packages/smooth_app/lib/helpers/strings_helper.dart index 48f631ff09e..055db2cb4db 100644 --- a/packages/smooth_app/lib/helpers/strings_helper.dart +++ b/packages/smooth_app/lib/helpers/strings_helper.dart @@ -110,25 +110,31 @@ class FormattedText extends StatelessWidget { @override Widget build(BuildContext context) { final TextStyle defaultTextStyle = textStyle ?? const TextStyle(); - return RichText( - text: TextSpan( - style: DefaultTextStyle.of(context).style, - children: TextHelper.getPartsBetweenSymbol( - text: text, - symbol: r'\*\*', - symbolLength: 2, - defaultStyle: defaultTextStyle, - highlightedStyle: const TextStyle(fontWeight: FontWeight.bold)) - .map( - ((String, TextStyle?) part) { - return TextSpan( - text: part.$1, - style: defaultTextStyle.merge(part.$2), - ); - }, - ).toList(growable: false), + return Semantics( + value: text.replaceAll(r'**', '').replaceAll('\n', ' '), + excludeSemantics: true, + child: RichText( + text: TextSpan( + style: DefaultTextStyle.of(context).style, + children: TextHelper.getPartsBetweenSymbol( + text: text, + symbol: r'\*\*', + symbolLength: 2, + defaultStyle: defaultTextStyle, + highlightedStyle: + const TextStyle(fontWeight: FontWeight.bold)) + .map( + ((String, TextStyle?) part) { + return TextSpan( + text: part.$1, + style: defaultTextStyle.merge(part.$2), + semanticsLabel: '-', + ); + }, + ).toList(growable: false), + ), + textAlign: textAlign ?? TextAlign.start, ), - textAlign: textAlign ?? TextAlign.start, ); } } diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index f966f3943b4..e4a63636224 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -781,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1226,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" diff --git a/packages/smooth_app/lib/pages/scan/camera_scan_page.dart b/packages/smooth_app/lib/pages/scan/camera_scan_page.dart index 4a6af676926..36c793cf0f5 100644 --- a/packages/smooth_app/lib/pages/scan/camera_scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/camera_scan_page.dart @@ -95,17 +95,21 @@ class _CameraScannerPageState extends State return ScreenVisibilityDetector( child: Stack( children: [ - GlobalVars.barcodeScanner.getScanner( - onScan: _onNewBarcodeDetected, - hapticFeedback: () => SmoothHapticFeedback.click(), - onCameraFlashError: CameraScannerPage.onCameraFlashError, - trackCustomEvent: AnalyticsHelper.trackCustomEvent, - hasMoreThanOneCamera: CameraHelper.hasMoreThanOneCamera, - toggleCameraModeTooltip: appLocalizations.camera_toggle_camera, - toggleFlashModeTooltip: appLocalizations.camera_toggle_flash, - contentPadding: _model.compareFeatureEnabled - ? EdgeInsets.only(top: _headerHeight ?? 0.0) - : null, + Semantics( + label: appLocalizations.camera_window_accessibility_label, + explicitChildNodes: true, + child: GlobalVars.barcodeScanner.getScanner( + onScan: _onNewBarcodeDetected, + hapticFeedback: () => SmoothHapticFeedback.click(), + onCameraFlashError: CameraScannerPage.onCameraFlashError, + trackCustomEvent: AnalyticsHelper.trackCustomEvent, + hasMoreThanOneCamera: CameraHelper.hasMoreThanOneCamera, + toggleCameraModeTooltip: appLocalizations.camera_toggle_camera, + toggleFlashModeTooltip: appLocalizations.camera_toggle_flash, + contentPadding: _model.compareFeatureEnabled + ? EdgeInsets.only(top: _headerHeight ?? 0.0) + : null, + ), ), Align( alignment: Alignment.topCenter, diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart index a693aecf8d5..31010c12ae9 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart @@ -32,20 +32,23 @@ class ScanMainCard extends StatelessWidget { expandedMode: true, ); } else { - return const Column( - children: [ - Expanded( - flex: 6, - child: _SearchCard( - expandedMode: false, + return Semantics( + explicitChildNodes: true, + child: const Column( + children: [ + Expanded( + flex: 6, + child: _SearchCard( + expandedMode: false, + ), ), - ), - SizedBox(height: MEDIUM_SPACE), - Expanded( - flex: 4, - child: ScanTagLine(), - ), - ], + SizedBox(height: MEDIUM_SPACE), + Expanded( + flex: 4, + child: ScanTagLine(), + ), + ], + ), ); } }, @@ -79,6 +82,7 @@ class _SearchCard extends StatelessWidget { horizontal: 0.0, vertical: VERY_SMALL_SPACE, ), + ignoreDefaultSemantics: true, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ @@ -123,54 +127,57 @@ class _SearchBar extends StatelessWidget { Theme.of(context).extension()!; final bool lightTheme = !context.watch().isDarkMode(context); - return SizedBox( - height: SEARCH_BAR_HEIGHT, - child: InkWell( - onTap: () => AppNavigator.of(context).push(AppRoutes.SEARCH), - borderRadius: BorderRadius.circular(30.0), - child: Ink( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30.0), - color: lightTheme ? Colors.white : theme.greyDark, - border: Border.all(color: theme.primaryBlack), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsetsDirectional.only( - start: 20.0, - end: 10.0, - bottom: 3.0, - ), - child: Text( - localizations.homepage_main_card_search_field_hint, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: lightTheme ? Colors.black : Colors.white, + return Semantics( + button: true, + child: SizedBox( + height: SEARCH_BAR_HEIGHT, + child: InkWell( + onTap: () => AppNavigator.of(context).push(AppRoutes.SEARCH), + borderRadius: BorderRadius.circular(30.0), + child: Ink( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + color: lightTheme ? Colors.white : theme.greyDark, + border: Border.all(color: theme.primaryBlack), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsDirectional.only( + start: 20.0, + end: 10.0, + bottom: 3.0, + ), + child: Text( + localizations.homepage_main_card_search_field_hint, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: lightTheme ? Colors.black : Colors.white, + ), ), ), ), - ), - AspectRatio( - aspectRatio: 1.0, - child: DecoratedBox( - decoration: BoxDecoration( - color: theme.primaryDark, - shape: BoxShape.circle, - ), - child: const Padding( - padding: EdgeInsets.all(10.0), - child: Search( - size: 20.0, - color: Colors.white, + AspectRatio( + aspectRatio: 1.0, + child: DecoratedBox( + decoration: BoxDecoration( + color: theme.primaryDark, + shape: BoxShape.circle, + ), + child: const Padding( + padding: EdgeInsets.all(10.0), + child: Search( + size: 20.0, + color: Colors.white, + ), ), ), - ), - ) - ], + ) + ], + ), ), ), ), diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart index cbd3869f349..dc92ae9469d 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart @@ -202,31 +202,36 @@ class _TagLineContentTitle extends StatelessWidget { Widget build(BuildContext context) { final SmoothColorsThemeExtension theme = Theme.of(context).extension()!; + final AppLocalizations localizations = AppLocalizations.of(context); - return ConstrainedBox( - constraints: const BoxConstraints(minHeight: 30.0), - child: Row( - children: [ - SizedBox.square( - dimension: 11.0, - child: DecoratedBox( - decoration: BoxDecoration( - color: indicatorColor ?? theme.secondaryLight, - borderRadius: const BorderRadius.all(ROUNDED_RADIUS), + return Semantics( + label: localizations.scan_tagline_news_item_accessibility(title), + excludeSemantics: true, + child: ConstrainedBox( + constraints: const BoxConstraints(minHeight: 30.0), + child: Row( + children: [ + SizedBox.square( + dimension: 11.0, + child: DecoratedBox( + decoration: BoxDecoration( + color: indicatorColor ?? theme.secondaryLight, + borderRadius: const BorderRadius.all(ROUNDED_RADIUS), + ), ), ), - ), - const SizedBox(width: SMALL_SPACE), - Expanded( - child: Text( - title, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16.0, - color: titleColor ?? Colors.white, - ), - )) - ], + const SizedBox(width: SMALL_SPACE), + Expanded( + child: Text( + title, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16.0, + color: titleColor ?? Colors.white, + ), + )) + ], + ), ), ); } @@ -369,7 +374,7 @@ class _ScanNewsFeedProvider extends ValueNotifier<_ScanTagLineState> { emit(const _ScanTagLineStateNoContent()); case AppNewsStateLoaded(): _onTagLineContentAvailable( - (_newsFeedProvider.state as AppNewsStateLoaded).tagLineContent); + (_newsFeedProvider.state as AppNewsStateLoaded).content); } } From f6ec9dfee59f2a622ee109eea90f1b504dfddf3d Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Wed, 19 Jun 2024 13:23:36 +0200 Subject: [PATCH 29/85] feat: Spellchecker for OCR screens (#5409) * Spellchecker for OCR screens * Code formatting * Specify `async` on the callback of `onChanged` --- packages/smooth_app/lib/l10n/app_en.arb | 8 +++ .../user_preferences_dev_mode.dart | 13 ++++ .../pages/product/edit_ocr/edit_ocr_page.dart | 65 +++++++++++++++---- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index e4a63636224..2de8ee5e6cc 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1832,6 +1832,14 @@ "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart index ca57ab676a2..b6b83651a91 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart @@ -57,6 +57,8 @@ class UserPreferencesDevMode extends AbstractUserPreferences { static const String userPreferencesFlagAccessibilityEmoji = '__accessibilityEmoji'; static const String userPreferencesFlagUserOrderedKP = '__userOrderedKP'; + static const String userPreferencesFlagSpellCheckerOnOcr = + '__spellcheckerOcr'; final TextEditingController _textFieldController = TextEditingController(); @@ -325,6 +327,17 @@ class UserPreferencesDevMode extends AbstractUserPreferences { _showSuccessMessage(); }, ), + UserPreferencesItemSwitch( + title: appLocalizations.dev_mode_spellchecker_for_ocr_title, + subtitle: appLocalizations.dev_mode_spellchecker_for_ocr_subtitle, + value: + userPreferences.getFlag(userPreferencesFlagSpellCheckerOnOcr) ?? + false, + onChanged: (bool value) async => userPreferences.setFlag( + userPreferencesFlagSpellCheckerOnOcr, + value, + ), + ), UserPreferencesItemSection( label: appLocalizations.dev_mode_section_experimental_features, ), diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index f8862431125..2765704283b 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -1,9 +1,12 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:shimmer/shimmer.dart'; import 'package:smooth_app/background/background_task_details.dart'; +import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/data_models/up_to_date_mixin.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/database/transient_file.dart'; @@ -13,13 +16,16 @@ import 'package:smooth_app/generic_lib/loading_dialog.dart'; import 'package:smooth_app/generic_lib/widgets/picture_not_found.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; +import 'package:smooth_app/helpers/provider_helper.dart'; import 'package:smooth_app/pages/image_crop_page.dart'; +import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/edit_ocr/ocr_helper.dart'; import 'package:smooth_app/pages/product/explanation_widget.dart'; import 'package:smooth_app/pages/product/multilingual_helper.dart'; import 'package:smooth_app/pages/product/product_image_button.dart'; import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; part 'edit_ocr_main_action.dart'; @@ -295,17 +301,54 @@ class _EditOcrPageState extends State with UpToDateMixin { state: _extractState(transientFile), ), const SizedBox(height: MEDIUM_SPACE), - TextField( - controller: _controller, - decoration: InputDecoration( - fillColor: Colors.white.withOpacity(0.2), - filled: true, - enabledBorder: const OutlineInputBorder( - borderRadius: ANGULAR_BORDER_RADIUS, - ), - ), - maxLines: null, - textInputAction: TextInputAction.newline, + ConsumerFilter( + buildWhen: ( + UserPreferences? previousValue, + UserPreferences currentValue, + ) { + return previousValue?.getFlag(UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr) != + currentValue.getFlag(UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr); + }, + builder: ( + BuildContext context, + UserPreferences prefs, + Widget? child, + ) { + final ThemeData theme = Theme.of(context); + + return Theme( + data: theme.copyWith( + colorScheme: theme.colorScheme.copyWith( + onSurface: context + .read() + .isDarkMode(context) + ? Colors.white + : Colors.black, + ), + ), + child: TextField( + controller: _controller, + decoration: InputDecoration( + fillColor: Colors.white.withOpacity(0.2), + filled: true, + enabledBorder: const OutlineInputBorder( + borderRadius: ANGULAR_BORDER_RADIUS, + ), + ), + maxLines: null, + textInputAction: TextInputAction.newline, + spellCheckConfiguration: (prefs.getFlag( + UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr) ?? + false) && + (Platform.isAndroid || Platform.isIOS) + ? const SpellCheckConfiguration() + : const SpellCheckConfiguration.disabled(), + ), + ); + }, ), const SizedBox(height: SMALL_SPACE), ExplanationWidget( From 65dece635106513cf79d9f39678c1e2fe7f5386c Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 08:59:17 +0200 Subject: [PATCH 30/85] Accessibility of the website card improved (#5414) --- .../lib/pages/product/website_card.dart | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/website_card.dart b/packages/smooth_app/lib/pages/product/website_card.dart index 1f2a42bc671..28f3d400db0 100644 --- a/packages/smooth_app/lib/pages/product/website_card.dart +++ b/packages/smooth_app/lib/pages/product/website_card.dart @@ -12,45 +12,53 @@ class WebsiteCard extends StatelessWidget { @override Widget build(BuildContext context) { + final AppLocalizations localizations = AppLocalizations.of(context); final String website = _getWebsite(); + return buildProductSmoothCard( - body: InkWell( - onTap: () async => LaunchUrlHelper.launchURL(website), - borderRadius: ROUNDED_BORDER_RADIUS, - child: Container( - width: double.infinity, - padding: const EdgeInsetsDirectional.only( - start: LARGE_SPACE, - top: LARGE_SPACE, - bottom: LARGE_SPACE, - // To be perfectly aligned with arrows - end: 21.0, - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context).product_field_website_title, - style: Theme.of(context).textTheme.displaySmall, - ), - const SizedBox(height: SMALL_SPACE), - Text( - website, - overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith(color: Colors.blue), - ), - ], + body: Semantics( + label: localizations.product_field_website_title, + value: Uri.parse(website).host, + link: true, + excludeSemantics: true, + child: InkWell( + onTap: () async => LaunchUrlHelper.launchURL(website), + borderRadius: ROUNDED_BORDER_RADIUS, + child: Container( + width: double.infinity, + padding: const EdgeInsetsDirectional.only( + start: LARGE_SPACE, + top: LARGE_SPACE, + bottom: LARGE_SPACE, + // To be perfectly aligned with arrows + end: 21.0, + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + localizations.product_field_website_title, + style: Theme.of(context).textTheme.displaySmall, + ), + const SizedBox(height: SMALL_SPACE), + Text( + website, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.blue), + ), + ], + ), ), - ), - const Icon(Icons.open_in_new), - ], + const Icon(Icons.open_in_new), + ], + ), ), ), ), From 274d797d8b60d77c7d38cacab9930d3e0cf52b8e Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 17:26:29 +0200 Subject: [PATCH 31/85] Dev mode for app news: custom URI + manual refresh (#5416) --- .../news_feed/newsfeed_provider.dart | 32 ++-- packages/smooth_app/lib/l10n/app_en.arb | 26 +++ .../user_preferences_dev_mode.dart | 46 +++++ .../preferences/user_preferences_widgets.dart | 157 ++++++++++++++++++ 4 files changed, 251 insertions(+), 10 deletions(-) diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart index 5b4e157d0ee..bbcf9acaf04 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart @@ -26,12 +26,12 @@ class AppNewsProvider extends ChangeNotifier { AppNewsProvider(UserPreferences preferences) : _state = const AppNewsStateLoading(), _preferences = preferences, + _uriOverride = preferences.getDevModeString( + UserPreferencesDevMode.userPreferencesCustomNewsJSONURI), _domain = preferences.getDevModeString( - UserPreferencesDevMode.userPreferencesTestEnvDomain) ?? - '', + UserPreferencesDevMode.userPreferencesTestEnvDomain), _prodEnv = preferences - .getFlag(UserPreferencesDevMode.userPreferencesFlagProd) ?? - true { + .getFlag(UserPreferencesDevMode.userPreferencesFlagProd) { _preferences.addListener(_onPreferencesChanged); loadLatestNews(); } @@ -67,13 +67,13 @@ class AppNewsProvider extends ChangeNotifier { return; } - final AppNews? tagLine = await Isolate.run( + final AppNews? appNews = await Isolate.run( () => _parseJSONAndGetLocalizedContent(jsonString!, locale)); - if (tagLine == null) { + if (appNews == null) { _emit(const AppNewsStateError('Unable to parse the JSON news file')); Logs.e('Unable to parse the JSON news file'); } else { - _emit(AppNewsStateLoaded(tagLine)); + _emit(AppNewsStateLoaded(appNews, cacheFile.lastModifiedSync())); Logs.i('News ${forceUpdate ? 're' : ''}loaded'); } } @@ -106,7 +106,13 @@ class AppNewsProvider extends ChangeNotifier { try { final UriProductHelper uriProductHelper = ProductQuery.uriProductHelper; final Map headers = {}; - final Uri uri = uriProductHelper.getUri(path: _newsUrl); + final Uri uri; + + if (_uriOverride?.isNotEmpty == true) { + uri = Uri.parse(_uriOverride!); + } else { + uri = uriProductHelper.getUri(path: _newsUrl); + } if (uriProductHelper.userInfoForPatch != null) { headers['Authorization'] = @@ -158,10 +164,14 @@ class AppNewsProvider extends ChangeNotifier { bool? _prodEnv; String? _domain; + String? _uriOverride; /// [ProductQuery.uriProductHelper] is not synced yet, /// so we have to check it manually Future _onPreferencesChanged() async { + final String jsonURI = _preferences.getDevModeString( + UserPreferencesDevMode.userPreferencesCustomNewsJSONURI) ?? + ''; final String domain = _preferences.getDevModeString( UserPreferencesDevMode.userPreferencesTestEnvDomain) ?? ''; @@ -169,9 +179,10 @@ class AppNewsProvider extends ChangeNotifier { _preferences.getFlag(UserPreferencesDevMode.userPreferencesFlagProd) ?? true; - if (domain != _domain || prodEnv != _prodEnv) { + if (domain != _domain || prodEnv != _prodEnv || jsonURI != _uriOverride) { _domain = domain; _prodEnv = prodEnv; + _uriOverride = jsonURI; loadLatestNews(forceUpdate: true); } } @@ -192,9 +203,10 @@ final class AppNewsStateLoading extends AppNewsState { } class AppNewsStateLoaded extends AppNewsState { - const AppNewsStateLoaded(this.content); + const AppNewsStateLoaded(this.content, this.lastUpdate); final AppNews content; + final DateTime lastUpdate; } class AppNewsStateError extends AppNewsState { diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 2de8ee5e6cc..ce55b2f9466 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1716,6 +1716,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1824,6 +1849,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart index b6b83651a91..f14ae46d4f6 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart @@ -2,11 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/background/background_task_badge.dart'; import 'package:smooth_app/background/background_task_language_refresh.dart'; import 'package:smooth_app/data_models/continuous_scan_model.dart'; +import 'package:smooth_app/data_models/news_feed/newsfeed_provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/data_models/product_list.dart'; import 'package:smooth_app/database/dao_osm_location.dart'; @@ -59,6 +61,7 @@ class UserPreferencesDevMode extends AbstractUserPreferences { static const String userPreferencesFlagUserOrderedKP = '__userOrderedKP'; static const String userPreferencesFlagSpellCheckerOnOcr = '__spellcheckerOcr'; + static const String userPreferencesCustomNewsJSONURI = '__newsJsonURI'; final TextEditingController _textFieldController = TextEditingController(); @@ -266,6 +269,49 @@ class UserPreferencesDevMode extends AbstractUserPreferences { ), onTap: () async => _changeTestEnvDomain(), ), + UserPreferencesItemSection( + label: appLocalizations.dev_mode_section_news, + ), + UserPreferencesEditableItemTile( + title: appLocalizations.dev_preferences_news_custom_url_title, + subtitleWithEmptyValue: + appLocalizations.dev_preferences_news_custom_url_empty_value, + dialogAction: + appLocalizations.dev_preferences_news_custom_url_subtitle, + value: userPreferences + .getDevModeString(userPreferencesCustomNewsJSONURI), + onNewValue: (String newUrl) => userPreferences.setDevModeString( + userPreferencesCustomNewsJSONURI, + newUrl, + ), + validator: (String value) => + value.isEmpty || Uri.tryParse(value) != null, + ), + UserPreferencesItemTileBuilder( + title: appLocalizations.dev_preferences_news_provider_status_title, + subtitleBuilder: (BuildContext context) { + return Consumer( + builder: (_, AppNewsProvider provider, __) { + return Text(switch (provider.state) { + AppNewsStateLoading() => 'Loading...', + AppNewsStateLoaded(lastUpdate: final DateTime date) => + appLocalizations + .dev_preferences_news_provider_status_subtitle( + DateFormat.yMd().format(date), + ), + AppNewsStateError(exception: final dynamic e) => 'Error $e', + }); + }); + }, + trailingBuilder: (BuildContext context) { + return IconButton( + icon: const Icon(Icons.refresh), + onPressed: () => context + .read() + .loadLatestNews(forceUpdate: true), + ); + }, + ), UserPreferencesItemSection( label: appLocalizations.dev_mode_section_product_page, ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart index 44be303dd28..735c70731a4 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_widgets.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; import 'package:smooth_app/generic_lib/bottom_sheets/smooth_bottom_sheet.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/pages/preferences/user_preferences_item.dart'; import 'package:smooth_app/themes/smooth_theme_colors.dart'; @@ -164,6 +167,35 @@ class UserPreferencesItemTile implements UserPreferencesItem { ); } +/// Same as [UserPreferencesItemTile] but with [WidgetBuilder]. +class UserPreferencesItemTileBuilder implements UserPreferencesItem { + const UserPreferencesItemTileBuilder({ + required this.title, + required this.subtitleBuilder, + this.onTap, + this.leadingBuilder, + this.trailingBuilder, + }); + + final String title; + final WidgetBuilder subtitleBuilder; + final VoidCallback? onTap; + final WidgetBuilder? leadingBuilder; + final WidgetBuilder? trailingBuilder; + + @override + List get labels => [title]; + + @override + WidgetBuilder get builder => (final BuildContext context) => ListTile( + title: Text(title), + subtitle: subtitleBuilder.call(context), + onTap: onTap, + leading: leadingBuilder?.call(context), + trailing: trailingBuilder?.call(context), + ); +} + class UserPreferencesItemSection implements UserPreferencesItem { const UserPreferencesItemSection({ required this.label, @@ -495,3 +527,128 @@ class UserPreferenceListTile extends StatelessWidget { ); } } + +class UserPreferencesEditableItemTile extends UserPreferencesItemTile { + const UserPreferencesEditableItemTile({ + required super.title, + required String dialogAction, + required this.onNewValue, + this.subtitleWithEmptyValue, + this.validator, + this.hint, + this.value, + }) : assert(dialogAction.length > 0), + super(subtitle: dialogAction); + + final String? value; + final String? hint; + final String? subtitleWithEmptyValue; + final bool Function(String)? validator; + final Function(String) onNewValue; + + @override + WidgetBuilder get builder => (BuildContext context) { + return ListTile( + title: Text(title), + subtitle: Text(value?.isNotEmpty == true + ? value! + : (subtitleWithEmptyValue ?? '-')), + onTap: () async => _showInputTextDialog(context), + ); + }; + + Future _showInputTextDialog(BuildContext context) async { + final TextEditingController controller = + TextEditingController(text: value ?? ''); + + final dynamic res = await showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + + return ChangeNotifierProvider.value( + value: controller, + child: Consumer( + builder: + (BuildContext context, TextEditingController controller, _) { + return SmoothAlertDialog( + title: title, + close: true, + body: _UserPreferencesEditableDialogContent( + title: subtitle!, + hint: hint, + ), + positiveAction: SmoothActionButton( + text: appLocalizations.okay, + onPressed: validator?.call(controller.text) != false + ? () => Navigator.of(context).pop(controller.text) + : null, + ), + negativeAction: SmoothActionButton( + text: appLocalizations.cancel, + onPressed: () => Navigator.of(context).pop(), + ), + ); + }, + ), + ); + }, + ); + + if (res is String && res != value) { + onNewValue.call(res); + } + } +} + +class _UserPreferencesEditableDialogContent extends StatefulWidget { + const _UserPreferencesEditableDialogContent({ + required this.title, + this.hint, + }); + + final String title; + final String? hint; + + @override + State<_UserPreferencesEditableDialogContent> createState() => + _InputTextDialogBodyState(); +} + +class _InputTextDialogBodyState + extends State<_UserPreferencesEditableDialogContent> { + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(widget.title), + const SizedBox(height: 10), + TextField( + controller: Provider.of(context), + autocorrect: false, + autofocus: true, + textInputAction: TextInputAction.send, + decoration: InputDecoration( + hintText: widget.hint, + suffix: Semantics( + button: true, + label: MaterialLocalizations.of(context).deleteButtonTooltip, + excludeSemantics: true, + child: InkWell( + onTap: () => context.read().clear(), + customBorder: const CircleBorder(), + child: const Padding( + padding: EdgeInsetsDirectional.all(SMALL_SPACE), + child: Icon(Icons.clear), + ), + ), + ), + ), + onSubmitted: (String value) => Navigator.of(context).pop(value), + ), + ], + ); + } +} From b322c683488bc78468f063d855a6d6df1b4bec84 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 17:39:21 +0200 Subject: [PATCH 32/85] Cloud upload indicator for the gallery (#5419) --- packages/smooth_app/assets/animations/off.riv | Bin 90021 -> 117861 bytes .../product/product_image_gallery_view.dart | 43 +++++++++++++++--- .../lib/resources/app_animations.dart | 15 ++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/packages/smooth_app/assets/animations/off.riv b/packages/smooth_app/assets/animations/off.riv index de111e2ade56610cf91f9657fa3886a5f4f23b9d..f3d36c7ff93661a94e747a2a605df7ae1e58f756 100644 GIT binary patch delta 10059 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 delta 4529 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 a)$m+zQlLv3+WRbRkq!>>$S diff --git a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart index eb923c6fb3f..4c4a217c088 100644 --- a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart +++ b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart @@ -17,6 +17,7 @@ import 'package:smooth_app/pages/image_crop_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/product_image_swipeable_view.dart'; import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/resources/app_animations.dart'; import 'package:smooth_app/widgets/slivers.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -190,6 +191,8 @@ class _PhotoRow extends StatelessWidget { @override Widget build(BuildContext context) { final ImageField imageField = _getImageField(position); + final TransientFile transientFile = _getTransientFile(imageField); + return Padding( padding: const EdgeInsets.only( top: SMALL_SPACE, @@ -201,12 +204,40 @@ class _PhotoRow extends StatelessWidget { ), child: Column( children: [ - AspectRatio( - aspectRatio: 1.0, - child: SmoothImage( - rounded: false, - imageProvider: _getTransientFile(imageField).getImageProvider(), - ), + Stack( + children: [ + AspectRatio( + aspectRatio: 1.0, + child: SmoothImage( + rounded: false, + imageProvider: transientFile.getImageProvider(), + ), + ), + if (transientFile.isImageAvailable() && + !transientFile.isServerImage()) + Positioned.directional( + textDirection: Directionality.of(context), + bottom: VERY_SMALL_SPACE, + end: VERY_SMALL_SPACE, + width: 30.0, + height: 30.0, + child: DecoratedBox( + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.5), + shape: BoxShape.circle, + ), + child: const Padding( + padding: EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: SMALL_SPACE, + top: SMALL_SPACE, + bottom: SMALL_SPACE - 1.0, + ), + child: CloudUploadAnimation(), + ), + ), + ), + ], ), Expanded( child: Center( diff --git a/packages/smooth_app/lib/resources/app_animations.dart b/packages/smooth_app/lib/resources/app_animations.dart index 1acdaaf48f1..d128b99a2e2 100644 --- a/packages/smooth_app/lib/resources/app_animations.dart +++ b/packages/smooth_app/lib/resources/app_animations.dart @@ -73,6 +73,21 @@ class BarcodeAnimation extends StatelessWidget { } } +class CloudUploadAnimation extends StatelessWidget { + const CloudUploadAnimation({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return RiveAnimation.direct( + AnimationsLoader.of(context), + artboard: 'Cloud upload', + animations: const ['Animation'], + ); + } +} + class ConsentAnimation extends StatelessWidget { const ConsentAnimation({ super.key, From 7ee3a26991e33637aa44de9269150c7aaa78ddb0 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 17:43:32 +0200 Subject: [PATCH 33/85] chore: "Take a picture" button now distinguishes "Take a picture" VS "Take a new picture" (#5396) * Difference between Take a picture / Take a new picture * Apply suggestions from code review --------- Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_en.arb | 8 +++-- .../pages/product/edit_ocr/edit_ocr_page.dart | 30 +++++++++++++++---- .../pages/product/product_image_button.dart | 2 ++ .../product/product_image_local_button.dart | 8 +++-- .../pages/product/product_image_viewer.dart | 28 +++++++++++++---- 5 files changed, 61 insertions(+), 15 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index ce55b2f9466..a40c2acb4bb 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -2203,9 +2203,13 @@ } } }, - "capture": "Capture New", + "capture": "Take a new picture", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index 2765704283b..88479a33be6 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -157,11 +157,16 @@ class _EditOcrPageState extends State with UpToDateMixin { ); } - Widget _getImageButton(final ProductImageButtonType type) => Padding( + Widget _getImageButton( + final ProductImageButtonType type, + final bool imageExists, + ) => + Padding( padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE), child: type.getButton( product: upToDateProduct, imageField: _helper.getImageField(), + imageExists: imageExists, language: _multilingualHelper.getCurrentLanguage(), isLoggedInMandatory: widget.isLoggedInMandatory, borderWidth: 2, @@ -223,6 +228,8 @@ class _EditOcrPageState extends State with UpToDateMixin { final OpenFoodFactsLanguage language = _multilingualHelper.getCurrentLanguage(); final ImageProvider? imageProvider = transientFile.getImageProvider(); + final bool imageExists = imageProvider != null; + return Align( alignment: AlignmentDirectional.bottomStart, child: Column( @@ -245,10 +252,16 @@ class _EditOcrPageState extends State with UpToDateMixin { mainAxisSize: MainAxisSize.max, children: [ Expanded( - child: _getImageButton(ProductImageButtonType.server), + child: _getImageButton( + ProductImageButtonType.server, + imageExists, + ), ), Expanded( - child: _getImageButton(ProductImageButtonType.local), + child: _getImageButton( + ProductImageButtonType.local, + imageExists, + ), ), ], ), @@ -259,11 +272,16 @@ class _EditOcrPageState extends State with UpToDateMixin { mainAxisSize: MainAxisSize.max, children: [ Expanded( - child: - _getImageButton(ProductImageButtonType.unselect), + child: _getImageButton( + ProductImageButtonType.unselect, + imageExists, + ), ), Expanded( - child: _getImageButton(ProductImageButtonType.edit), + child: _getImageButton( + ProductImageButtonType.edit, + imageExists, + ), ), ], ), diff --git a/packages/smooth_app/lib/pages/product/product_image_button.dart b/packages/smooth_app/lib/pages/product/product_image_button.dart index f977ce74f05..2c6352d9f24 100644 --- a/packages/smooth_app/lib/pages/product/product_image_button.dart +++ b/packages/smooth_app/lib/pages/product/product_image_button.dart @@ -65,6 +65,7 @@ enum ProductImageButtonType { required final OpenFoodFactsLanguage language, required final bool isLoggedInMandatory, final double? borderWidth, + required bool imageExists, }) => switch (this) { ProductImageButtonType.local => ProductImageLocalButton( @@ -73,6 +74,7 @@ enum ProductImageButtonType { language: language, isLoggedInMandatory: isLoggedInMandatory, borderWidth: borderWidth, + imageExists: imageExists, ), ProductImageButtonType.server => ProductImageServerButton( product: product, diff --git a/packages/smooth_app/lib/pages/product/product_image_local_button.dart b/packages/smooth_app/lib/pages/product/product_image_local_button.dart index 4f4a687db3b..049cffa4291 100644 --- a/packages/smooth_app/lib/pages/product/product_image_local_button.dart +++ b/packages/smooth_app/lib/pages/product/product_image_local_button.dart @@ -11,15 +11,19 @@ class ProductImageLocalButton extends ProductImageButton { required super.imageField, required super.language, required super.isLoggedInMandatory, + required this.imageExists, super.borderWidth, }); + final bool imageExists; + @override IconData getIconData() => Icons.add_a_photo; @override - String getLabel(final AppLocalizations appLocalizations) => - appLocalizations.capture; + String getLabel(final AppLocalizations appLocalizations) => imageExists + ? appLocalizations.capture + : appLocalizations.capture_new_picture; @override Future action(final BuildContext context) async { diff --git a/packages/smooth_app/lib/pages/product/product_image_viewer.dart b/packages/smooth_app/lib/pages/product/product_image_viewer.dart index 4b8c84457a3..1f43d5cfd76 100644 --- a/packages/smooth_app/lib/pages/product/product_image_viewer.dart +++ b/packages/smooth_app/lib/pages/product/product_image_viewer.dart @@ -44,11 +44,16 @@ class _ProductImageViewerState extends State initUpToDate(widget.product, context.read()); } - Widget _getImageButton(final ProductImageButtonType type) => Padding( + Widget _getImageButton( + final ProductImageButtonType type, + final bool imageExists, + ) => + Padding( padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE), child: type.getButton( product: upToDateProduct, imageField: widget.imageField, + imageExists: imageExists, language: widget.language, isLoggedInMandatory: widget.isLoggedInMandatory, ), @@ -65,6 +70,7 @@ class _ProductImageViewerState extends State widget.language, ); final ImageProvider? imageProvider = _getTransientFile().getImageProvider(); + final bool imageExists = imageProvider != null; final Iterable selectedLanguages = getProductImageLanguages( upToDateProduct, @@ -193,10 +199,16 @@ class _ProductImageViewerState extends State mainAxisSize: MainAxisSize.max, children: [ Expanded( - child: _getImageButton(ProductImageButtonType.server), + child: _getImageButton( + ProductImageButtonType.server, + imageExists, + ), ), Expanded( - child: _getImageButton(ProductImageButtonType.local), + child: _getImageButton( + ProductImageButtonType.local, + imageExists, + ), ), ], ), @@ -207,10 +219,16 @@ class _ProductImageViewerState extends State mainAxisSize: MainAxisSize.max, children: [ Expanded( - child: _getImageButton(ProductImageButtonType.unselect), + child: _getImageButton( + ProductImageButtonType.unselect, + imageExists, + ), ), Expanded( - child: _getImageButton(ProductImageButtonType.edit), + child: _getImageButton( + ProductImageButtonType.edit, + imageExists, + ), ), ], ), From da76dd2cf099bbf90dcbec1ebcb83aab43ae30b4 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 17:44:40 +0200 Subject: [PATCH 34/85] Accessibility improvements for the list of prices (#5413) --- .../widgets/smooth_back_button.dart | 18 ++- packages/smooth_app/lib/l10n/app_en.arb | 43 ++++++ .../lib/pages/prices/price_button.dart | 37 +++-- .../lib/pages/prices/price_data_widget.dart | 100 +++++++------ .../pages/prices/price_product_widget.dart | 134 +++++++++++------- .../lib/pages/prices/price_user_button.dart | 1 + .../lib/pages/prices/prices_page.dart | 15 +- 7 files changed, 235 insertions(+), 113 deletions(-) diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart index 038dc1359e6..ca4e99636d1 100644 --- a/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_back_button.dart @@ -16,13 +16,21 @@ class SmoothBackButton extends StatelessWidget { final Color? iconColor; @override - Widget build(BuildContext context) => Material( - type: MaterialType.transparency, + Widget build(BuildContext context) { + final MaterialLocalizations localizations = + MaterialLocalizations.of(context); + + return Material( + type: MaterialType.transparency, + child: Semantics( + value: localizations.backButtonTooltip, + button: true, + excludeSemantics: true, child: InkWell( onTap: onPressed ?? () => Navigator.maybePop(context), customBorder: const CircleBorder(), child: Tooltip( - message: MaterialLocalizations.of(context).backButtonTooltip, + message: localizations.backButtonTooltip, child: Padding( padding: _iconPadding, child: Icon( @@ -36,7 +44,9 @@ class SmoothBackButton extends StatelessWidget { ), ), ), - ); + ), + ); + } /// The iOS/macOS icon requires a little padding to be well-centered EdgeInsetsGeometry get _iconPadding { diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index a40c2acb4bb..11fb0307a4e 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1765,6 +1765,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1786,6 +1798,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", diff --git a/packages/smooth_app/lib/pages/prices/price_button.dart b/packages/smooth_app/lib/pages/prices/price_button.dart index d07bf5fcfd4..8b68413bf5e 100644 --- a/packages/smooth_app/lib/pages/prices/price_button.dart +++ b/packages/smooth_app/lib/pages/prices/price_button.dart @@ -6,6 +6,7 @@ class PriceButton extends StatelessWidget { this.title, this.iconData, this.buttonStyle, + this.tooltip, required this.onPressed, }); @@ -13,28 +14,44 @@ class PriceButton extends StatelessWidget { final IconData? iconData; final ButtonStyle? buttonStyle; final VoidCallback? onPressed; + final String? tooltip; @override Widget build(BuildContext context) { + final Widget widget; + if (iconData == null) { - return ElevatedButton( + widget = ElevatedButton( onPressed: onPressed, style: buttonStyle, child: Text(title!), ); - } - if (title == null) { - return ElevatedButton( + } else if (title == null) { + widget = ElevatedButton( onPressed: onPressed, style: buttonStyle, child: Icon(iconData), ); + } else { + widget = ElevatedButton.icon( + onPressed: onPressed, + icon: Icon(iconData), + label: Text(title!), + style: buttonStyle, + ); + } + + if (tooltip?.isNotEmpty == true) { + return Semantics( + value: tooltip, + button: true, + excludeSemantics: true, + child: Tooltip( + message: tooltip, + child: widget, + ), + ); } - return ElevatedButton.icon( - onPressed: onPressed, - icon: Icon(iconData), - label: Text(title!), - style: buttonStyle, - ); + return widget; } } diff --git a/packages/smooth_app/lib/pages/prices/price_data_widget.dart b/packages/smooth_app/lib/pages/prices/price_data_widget.dart index 142f6d7c1e3..b246c3d3bb5 100644 --- a/packages/smooth_app/lib/pages/prices/price_data_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_data_widget.dart @@ -62,53 +62,67 @@ class PriceDataWidget extends StatelessWidget { final String? pricePerKg = getPricePerKg(); final String? notDiscountedPrice = getNotDiscountedPrice(); - return Wrap( - alignment: WrapAlignment.start, - crossAxisAlignment: WrapCrossAlignment.center, - spacing: MEDIUM_SPACE, - children: [ - Text( - '${currencyFormat.format(price.price)}' - ' ${pricePerKg == null ? '' : ' ($pricePerKg)'}', - ), - Text(dateFormat.format(price.date)), - if (notDiscountedPrice != null) Text('($notDiscountedPrice)'), - if (locationTitle != null) - // TODO(monsieurtanuki): open a still-to-be-done "price x location" page - PriceButton( - title: locationTitle, - iconData: Icons.location_on_outlined, - onPressed: () {}, - ), - if (model.displayOwner) PriceUserButton(price.owner), - Tooltip( - message: '${dateFormat.format(price.created)}' - ' ' - '${timeFormat.format(price.created)}', - child: PriceButton( - // TODO(monsieurtanuki): misleading "active" button - onPressed: () {}, - iconData: Icons.history, - title: ProductQueryPageHelper.getDurationStringFromTimestamp( - price.created.millisecondsSinceEpoch, - context, - compact: true, + final String priceLabel = '${currencyFormat.format(price.price)}' + ' ${pricePerKg == null ? '' : ' ($pricePerKg)'}'; + return Semantics( + container: true, + explicitChildNodes: false, + label: appLocalizations.prices_entry_accessibility_label( + priceLabel, + locationTitle ?? '-', + dateFormat.format(price.date), + price.owner, + ), + child: Wrap( + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.center, + spacing: MEDIUM_SPACE, + children: [ + ExcludeSemantics(child: Text(priceLabel)), + ExcludeSemantics(child: Text(dateFormat.format(price.date))), + if (notDiscountedPrice != null) Text('($notDiscountedPrice)'), + if (locationTitle != null) + // TODO(monsieurtanuki): open a still-to-be-done "price x location" page + ExcludeSemantics( + child: PriceButton( + title: locationTitle, + iconData: Icons.location_on_outlined, + onPressed: () {}, + ), ), - ), - ), - if (price.proof?.filePath != null) - PriceButton( - iconData: Icons.image, - onPressed: () async => Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => PriceProofPage( - price.proof!, + if (model.displayOwner) PriceUserButton(price.owner), + ExcludeSemantics( + child: Tooltip( + message: '${dateFormat.format(price.created)}' + ' ' + '${timeFormat.format(price.created)}', + child: PriceButton( + // TODO(monsieurtanuki): misleading "active" button + onPressed: () {}, + iconData: Icons.history, + title: ProductQueryPageHelper.getDurationStringFromTimestamp( + price.created.millisecondsSinceEpoch, + context, + compact: true, ), ), - ), // PriceProofPage + ), ), - ], + if (price.proof?.filePath != null) + PriceButton( + iconData: Icons.image, + tooltip: appLocalizations.prices_open_proof, + onPressed: () async => Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => PriceProofPage( + price.proof!, + ), + ), + ), // PriceProofPage + ), + ], + ), ); } diff --git a/packages/smooth_app/lib/pages/prices/price_product_widget.dart b/packages/smooth_app/lib/pages/prices/price_product_widget.dart index e27b604313c..9e142a37a2b 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_widget.dart @@ -31,62 +31,94 @@ class PriceProductWidget extends StatelessWidget { final String? quantity = priceProduct.quantity == null ? null : '${priceProduct.quantity} ${priceProduct.quantityUnit ?? 'g'}'; - return Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: size, - child: SmoothImage( + return Semantics( + label: _generateSemanticsLabel( + appLocalizations, + name, + brands, + quantity, + priceCount, + ), + container: true, + excludeSemantics: true, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( width: size, - height: size, - imageProvider: imageURL == null ? null : NetworkImage(imageURL), + child: SmoothImage( + width: size, + height: size, + imageProvider: imageURL == null ? null : NetworkImage(imageURL), + ), ), - ), - const SizedBox(width: SMALL_SPACE), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AutoSizeText( - name, - maxLines: 2, - style: Theme.of(context).textTheme.titleMedium, - ), - Wrap( - spacing: VERY_SMALL_SPACE, - crossAxisAlignment: WrapCrossAlignment.center, - runSpacing: 0, - children: [ - PriceCountWidget( - priceCount, - priceProduct: priceProduct, - enableCountButton: model.enableCountButton, - ), - if (brands != null) - for (final String brand in brands) + const SizedBox(width: SMALL_SPACE), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AutoSizeText( + name, + maxLines: 2, + style: Theme.of(context).textTheme.titleMedium, + ), + Wrap( + spacing: VERY_SMALL_SPACE, + crossAxisAlignment: WrapCrossAlignment.center, + runSpacing: 0, + children: [ + PriceCountWidget( + priceCount, + priceProduct: priceProduct, + enableCountButton: model.enableCountButton, + ), + if (brands != null) + for (final String brand in brands) + PriceButton( + title: brand, + onPressed: () {}, + ), + if (quantity != null) Text(quantity), + if (unknown) PriceButton( - title: brand, - onPressed: () {}, - ), - if (quantity != null) Text(quantity), - if (unknown) - PriceButton( - title: appLocalizations.prices_unknown_product, - iconData: Icons.warning, - onPressed: null, - buttonStyle: ElevatedButton.styleFrom( - disabledForegroundColor: Colors.red, - disabledBackgroundColor: Colors.red[100], + title: appLocalizations.prices_unknown_product, + iconData: Icons.warning, + onPressed: null, + buttonStyle: ElevatedButton.styleFrom( + disabledForegroundColor: Colors.red, + disabledBackgroundColor: Colors.red[100], + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), - ), - ], + ], + ), + ); + } + + String _generateSemanticsLabel( + AppLocalizations appLocalizations, + String productName, + List? brands, + String? quantity, + int priceCount, + ) { + final StringBuffer product = StringBuffer(productName); + if (brands?.isNotEmpty == true) { + product.write(' - ${brands!.join(', ')}'); + } + if (quantity?.isNotEmpty == true) { + product.write(' ($quantity)'); + } + + return appLocalizations.prices_product_accessibility_summary( + priceCount, + product.toString(), ); } } diff --git a/packages/smooth_app/lib/pages/prices/price_user_button.dart b/packages/smooth_app/lib/pages/prices/price_user_button.dart index 6d8e86b8229..d7bcd09da52 100644 --- a/packages/smooth_app/lib/pages/prices/price_user_button.dart +++ b/packages/smooth_app/lib/pages/prices/price_user_button.dart @@ -53,6 +53,7 @@ class PriceUserButton extends StatelessWidget { @override Widget build(BuildContext context) => PriceButton( + tooltip: AppLocalizations.of(context).prices_open_user_proofs(user), title: user, iconData: Icons.account_box, onPressed: () async => showUserPrices( diff --git a/packages/smooth_app/lib/pages/prices/prices_page.dart b/packages/smooth_app/lib/pages/prices/prices_page.dart index 51e9201657b..c2f9ce579e2 100644 --- a/packages/smooth_app/lib/pages/prices/prices_page.dart +++ b/packages/smooth_app/lib/pages/prices/prices_page.dart @@ -26,11 +26,16 @@ class PricesPage extends StatelessWidget { ), subTitle: model.subtitle == null ? null : Text(model.subtitle!), actions: [ - IconButton( - tooltip: appLocalizations.prices_app_button, - icon: const Icon(Icons.open_in_new), - onPressed: () async => LaunchUrlHelper.launchURL( - model.uri.toString(), + Semantics( + link: true, + label: appLocalizations.prices_app_button, + excludeSemantics: true, + child: IconButton( + tooltip: appLocalizations.prices_app_button, + icon: const ExcludeSemantics(child: Icon(Icons.open_in_new)), + onPressed: () async => LaunchUrlHelper.launchURL( + model.uri.toString(), + ), ), ), ], From ebb90b171a87657b7ab6ac5f8aefca74211908ea Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 17:45:56 +0200 Subject: [PATCH 35/85] feat: Crop page: increase paddings (#5279) * Crop page: increase paddings * Fix: regression on Product image page --- packages/smooth_app/lib/pages/crop_page.dart | 100 ++++++++++-------- .../lib/pages/product/edit_image_button.dart | 21 +++- 2 files changed, 75 insertions(+), 46 deletions(-) diff --git a/packages/smooth_app/lib/pages/crop_page.dart b/packages/smooth_app/lib/pages/crop_page.dart index c4afd928f5b..e7a832c5c71 100644 --- a/packages/smooth_app/lib/pages/crop_page.dart +++ b/packages/smooth_app/lib/pages/crop_page.dart @@ -179,47 +179,52 @@ class _CropPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (!_isErasing) - _IconButton( - iconData: Icons.rotate_90_degrees_ccw_outlined, - onPressed: () => setState( - () { - _controller.rotateLeft(); - _eraserModel.rotation = _controller.rotation; - }, + Padding( + padding: const EdgeInsetsDirectional.only( + top: SMALL_SPACE, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (!_isErasing) + _IconButton( + iconData: Icons.rotate_90_degrees_ccw_outlined, + onPressed: () => setState( + () { + _controller.rotateLeft(); + _eraserModel.rotation = _controller.rotation; + }, + ), ), - ), - if (widget.cropHelper.enableEraser) - _IconButton( - iconData: _isErasing ? Icons.crop : Icons.brush, - color: _isErasing ? null : EraserPainter.color, - onPressed: () => setState( - () => _isErasing = !_isErasing, + if (widget.cropHelper.enableEraser) + _IconButton( + iconData: _isErasing ? Icons.crop : Icons.brush, + color: _isErasing ? null : EraserPainter.color, + onPressed: () => setState( + () => _isErasing = !_isErasing, + ), ), - ), - if (_isErasing) - _IconButton( - iconData: Icons.undo, - onPressed: _eraserModel.isEmpty - ? null - : () => setState( - () => _eraserModel.undo(), - ), - ), - if (!_isErasing) - _IconButton( - iconData: Icons.rotate_90_degrees_cw_outlined, - onPressed: () => setState( - () { - _controller.rotateRight(); - _eraserModel.rotation = _controller.rotation; - }, + if (_isErasing) + _IconButton( + iconData: Icons.undo, + onPressed: _eraserModel.isEmpty + ? null + : () => setState( + () => _eraserModel.undo(), + ), ), - ), - ], + if (!_isErasing) + _IconButton( + iconData: Icons.rotate_90_degrees_cw_outlined, + onPressed: () => setState( + () { + _controller.rotateRight(); + _eraserModel.rotation = _controller.rotation; + }, + ), + ), + ], + ), ), Expanded( child: Stack( @@ -275,12 +280,19 @@ class _CropPageState extends State { ], ), ), - Center( - child: EditImageButton( - iconData: widget.cropHelper.getProcessIcon(), - label: - widget.cropHelper.getProcessLabel(appLocalizations), - onPressed: () async => _saveImageAndPop(), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: VERY_SMALL_SPACE, + vertical: SMALL_SPACE, + ), + child: SizedBox( + width: double.infinity, + child: EditImageButton.center( + iconData: widget.cropHelper.getProcessIcon(), + label: widget.cropHelper + .getProcessLabel(appLocalizations), + onPressed: () async => _saveImageAndPop(), + ), ), ), ], diff --git a/packages/smooth_app/lib/pages/product/edit_image_button.dart b/packages/smooth_app/lib/pages/product/edit_image_button.dart index e7ab6df11e3..bc644102552 100644 --- a/packages/smooth_app/lib/pages/product/edit_image_button.dart +++ b/packages/smooth_app/lib/pages/product/edit_image_button.dart @@ -9,12 +9,21 @@ class EditImageButton extends StatelessWidget { required this.label, required this.onPressed, this.borderWidth, - }); + }) : _centerContent = false; + + /// Centered version of the button. + const EditImageButton.center({ + required this.iconData, + required this.label, + required this.onPressed, + this.borderWidth, + }) : _centerContent = true; final IconData iconData; final String label; final VoidCallback onPressed; final double? borderWidth; + final bool _centerContent; @override Widget build(BuildContext context) { @@ -36,10 +45,18 @@ class EditImageButton extends StatelessWidget { width: borderWidth!, ), ), + padding: _centerContent + ? MaterialStateProperty.all( + const EdgeInsets.symmetric( + vertical: LARGE_SPACE, + ), + ) + : null, + alignment: _centerContent ? AlignmentDirectional.center : null, ), onPressed: onPressed, label: SizedBox( - width: double.infinity, + width: !_centerContent ? double.infinity : null, child: Padding( padding: EdgeInsets.all(borderWidth ?? 0), child: AutoSizeText( From b6f2f5ccd98937476a77895a1a9f5c76a9e582b5 Mon Sep 17 00:00:00 2001 From: Open Food Facts Bot <119524357+openfoodfacts-bot@users.noreply.github.com> Date: Thu, 20 Jun 2024 18:06:21 +0200 Subject: [PATCH 36/85] chore: New translations to review and merge (#5357) * New translations app_en.arb (Kyrgyz) * New translations app_en.arb (Malay) * New translations app_en.arb (Maori) * New translations app_en.arb (Telugu) * New translations app_en.arb (English, Australia) * New translations app_en.arb (English, United Kingdom) * New translations app_en.arb (Tagalog) * New translations app_en.arb (Burmese) * New translations app_en.arb (Yiddish) * New translations app_en.arb (Maltese) * New translations app_en.arb (Welsh) * New translations app_en.arb (Faroese) * New translations app_en.arb (Uyghur) * New translations app_en.arb (Filipino) * New translations app_en.arb (Luxembourgish) * New translations app_en.arb (Chinese Traditional, Hong Kong) * New translations app_en.arb (Tatar) * New translations app_en.arb (Malayalam) * New translations app_en.arb (Breton) * New translations app_en.arb (Romansh) * New translations app_en.arb (Tibetan) * New translations app_en.arb (Latin) * New translations app_en.arb (Flemish) * New translations app_en.arb (Bosnian) * New translations app_en.arb (Sinhala) * New translations app_en.arb (Cornish) * New translations app_en.arb (Uzbek) * New translations app_en.arb (Kannada) * New translations app_en.arb (Akan) * New translations app_en.arb (Songhay) * New translations app_en.arb (Assamese) * New translations app_en.arb (Scottish Gaelic) * New translations app_en.arb (Wolof) * New translations app_en.arb (Southern Ndebele) * New translations app_en.arb (Walloon) * New translations app_en.arb (Asturian) * New translations app_en.arb (Malagasy) * New translations app_en.arb (Acholi) * New translations app_en.arb (Swahili) * New translations app_en.arb (Odia) * New translations app_en.arb (Norwegian Bokmal) * New translations app_en.arb (Occitan) * New translations app_en.arb (Valencian) * New translations app_en.arb (Serbian (Latin)) * New translations app_en.arb (Amharic) * New translations app_en.arb (Nepali) * New translations app_en.arb (Montenegrin (Cyrillic)) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (Tahitian) * New translations app_en.arb (Hausa) * New translations app_en.arb (Chuvash) * New translations app_en.arb (Berber) * New translations app_en.arb (Scots) * New translations app_en.arb (Tajik) * New translations app_en.arb (Lao) * New translations app_en.arb (Quechua) * New translations app_en.arb (Somali) * New translations app_en.arb (Yoruba) * New translations app_en.arb (Afar) * New translations app_en.arb (Bambara) * New translations app_en.arb (Chechen) * New translations app_en.arb (Cherokee) * New translations app_en.arb (Corsican) * New translations app_en.arb (Haitian Creole) * New translations app_en.arb (Sichuan Yi) * New translations app_en.arb (Inuktitut) * New translations app_en.arb (Javanese) * New translations app_en.arb (Santali) * New translations app_en.arb (Sardinian) * New translations app_en.arb (Sindhi) * New translations app_en.arb (Sango) * New translations app_en.arb (Shona) * New translations app_en.arb (Tigrinya) * New translations app_en.arb (Sanskrit) * New translations app_en.arb (Seychellois Creole) * New translations app_en.arb (Venetian) * New translations app_en.arb (Southern Sami) * New translations app_en.arb (Akan, Twi) * New translations app_en.arb (Talossan) * New translations app_en.arb (Zeelandic) * New translations app_en.arb (Kabyle) * New translations app_en.arb (Urdu (India)) * New translations app_en.arb (LOLCAT) * New translations app_en.arb (Lithuanian) * New translations app_en.arb (Ukrainian) * New translations app_en.arb (Tamil) * New translations app_en.arb (German) * New translations app_en.arb (Dutch) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (Italian) * New translations app_en.arb (Slovak) * New translations app_en.arb (Italian) * New translations app_en.arb (Hebrew) * New translations app_en.arb (Romanian) * New translations app_en.arb (French) * New translations app_en.arb (Spanish) * New translations app_en.arb (Afrikaans) * New translations app_en.arb (Arabic) * New translations app_en.arb (Belarusian) * New translations app_en.arb (Bulgarian) * New translations app_en.arb (Catalan) * New translations app_en.arb (Czech) * New translations app_en.arb (Danish) * New translations app_en.arb (German) * New translations app_en.arb (Greek) * New translations app_en.arb (Basque) * New translations app_en.arb (Finnish) * New translations app_en.arb (Irish) * New translations app_en.arb (Gujarati) * New translations app_en.arb (Hungarian) * New translations app_en.arb (Armenian) * New translations app_en.arb (Japanese) * New translations app_en.arb (Georgian) * New translations app_en.arb (Korean) * New translations app_en.arb (Kurdish) * New translations app_en.arb (Lithuanian) * New translations app_en.arb (Mongolian) * New translations app_en.arb (Dutch) * New translations app_en.arb (Norwegian) * New translations app_en.arb (Punjabi) * New translations app_en.arb (Polish) * New translations app_en.arb (Portuguese) * New translations app_en.arb (Russian) * New translations app_en.arb (Slovak) * New translations app_en.arb (Slovenian) * New translations app_en.arb (Albanian) * New translations app_en.arb (Serbian (Cyrillic)) * New translations app_en.arb (Swati) * New translations app_en.arb (Southern Sotho) * New translations app_en.arb (Swedish) * New translations app_en.arb (Tswana) * New translations app_en.arb (Turkish) * New translations app_en.arb (Tsonga) * New translations app_en.arb (Ukrainian) * New translations app_en.arb (Venda) * New translations app_en.arb (Xhosa) * New translations app_en.arb (Chinese Simplified) * New translations app_en.arb (Chinese Traditional) * New translations app_en.arb (Zulu) * New translations app_en.arb (English) * New translations app_en.arb (Esperanto) * New translations app_en.arb (Vietnamese) * New translations app_en.arb (Galician) * New translations app_en.arb (Icelandic) * New translations app_en.arb (Portuguese, Brazilian) * New translations app_en.arb (Indonesian) * New translations app_en.arb (Persian) * New translations app_en.arb (Khmer) * New translations app_en.arb (Tamil) * New translations app_en.arb (Bengali) * New translations app_en.arb (Marathi) * New translations app_en.arb (Thai) * New translations app_en.arb (Croatian) * New translations app_en.arb (Norwegian Nynorsk) * New translations app_en.arb (Kazakh) * New translations app_en.arb (Estonian) * New translations app_en.arb (Latvian) * New translations app_en.arb (Azerbaijani) * New translations app_en.arb (Hindi) * New translations app_en.arb (Kyrgyz) * New translations app_en.arb (Malay) * New translations app_en.arb (Maori) * New translations app_en.arb (Telugu) * New translations app_en.arb (English, Australia) * New translations app_en.arb (English, United Kingdom) * New translations app_en.arb (Tagalog) * New translations app_en.arb (Burmese) * New translations app_en.arb (Yiddish) * New translations app_en.arb (Maltese) * New translations app_en.arb (Welsh) * New translations app_en.arb (Faroese) * New translations app_en.arb (Uyghur) * New translations app_en.arb (Filipino) * New translations app_en.arb (Luxembourgish) * New translations app_en.arb (Chinese Traditional, Hong Kong) * New translations app_en.arb (Tatar) * New translations app_en.arb (Malayalam) * New translations app_en.arb (Breton) * New translations app_en.arb (Romansh) * New translations app_en.arb (Tibetan) * New translations app_en.arb (Latin) * New translations app_en.arb (Flemish) * New translations app_en.arb (Bosnian) * New translations app_en.arb (Sinhala) * New translations app_en.arb (Cornish) * New translations app_en.arb (Uzbek) * New translations app_en.arb (Kannada) * New translations app_en.arb (Akan) * New translations app_en.arb (Songhay) * New translations app_en.arb (Assamese) * New translations app_en.arb (Scottish Gaelic) * New translations app_en.arb (Wolof) * New translations app_en.arb (Southern Ndebele) * New translations app_en.arb (Walloon) * New translations app_en.arb (Asturian) * New translations app_en.arb (Malagasy) * New translations app_en.arb (Acholi) * New translations app_en.arb (Swahili) * New translations app_en.arb (Odia) * New translations app_en.arb (Norwegian Bokmal) * New translations app_en.arb (Occitan) * New translations app_en.arb (Valencian) * New translations app_en.arb (Serbian (Latin)) * New translations app_en.arb (Amharic) * New translations app_en.arb (Nepali) * New translations app_en.arb (Montenegrin (Cyrillic)) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (Tahitian) * New translations app_en.arb (Hausa) * New translations app_en.arb (Chuvash) * New translations app_en.arb (Berber) * New translations app_en.arb (Scots) * New translations app_en.arb (Tajik) * New translations app_en.arb (Lao) * New translations app_en.arb (Quechua) * New translations app_en.arb (Somali) * New translations app_en.arb (Yoruba) * New translations app_en.arb (Afar) * New translations app_en.arb (Bambara) * New translations app_en.arb (Chechen) * New translations app_en.arb (Cherokee) * New translations app_en.arb (Corsican) * New translations app_en.arb (Haitian Creole) * New translations app_en.arb (Sichuan Yi) * New translations app_en.arb (Inuktitut) * New translations app_en.arb (Javanese) * New translations app_en.arb (Santali) * New translations app_en.arb (Sardinian) * New translations app_en.arb (Sindhi) * New translations app_en.arb (Sango) * New translations app_en.arb (Shona) * New translations app_en.arb (Tigrinya) * New translations app_en.arb (Sanskrit) * New translations app_en.arb (Seychellois Creole) * New translations app_en.arb (Venetian) * New translations app_en.arb (Southern Sami) * New translations app_en.arb (Akan, Twi) * New translations app_en.arb (Talossan) * New translations app_en.arb (Zeelandic) * New translations app_en.arb (Kabyle) * New translations app_en.arb (Urdu (India)) * New translations app_en.arb (LOLCAT) * New translations app_en.arb (Dutch) * New translations app_en.arb (Ukrainian) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (German) * New translations app_en.arb (Thai) * New translations app_en.arb (German) * delete --------- Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_aa.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_af.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ak.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_am.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ar.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_as.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_az.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_be.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_bg.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_bm.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_bn.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_bo.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_br.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_bs.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ca.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ce.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_co.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_cs.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_cv.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_cy.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_da.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_de.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_el.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_en.arb | 4 +- packages/smooth_app/lib/l10n/app_eo.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_es.arb | 149 +++++++++++++++-- packages/smooth_app/lib/l10n/app_et.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_eu.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_fa.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_fi.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_fo.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_fr.arb | 85 ++++++++-- packages/smooth_app/lib/l10n/app_ga.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_gd.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_gl.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_gu.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ha.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_he.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_hi.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_hr.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ht.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_hu.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_hy.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_id.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ii.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_is.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_it.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_iu.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ja.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_jv.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ka.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_kk.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_km.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_kn.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ko.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ku.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_kw.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ky.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_la.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_lb.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_lo.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_lt.arb | 205 +++++++++++++++++++----- packages/smooth_app/lib/l10n/app_lv.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_mg.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_mi.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ml.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_mn.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_mr.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ms.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_mt.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_my.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_nb.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ne.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_nl.arb | 161 +++++++++++++++++-- packages/smooth_app/lib/l10n/app_nn.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_no.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_nr.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_oc.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_or.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_pa.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_pl.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_pt.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_qu.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_rm.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ro.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ru.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sa.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sc.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sd.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sg.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_si.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sk.arb | 153 ++++++++++++++++-- packages/smooth_app/lib/l10n/app_sl.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sn.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_so.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sq.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sr.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ss.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_st.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sv.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_sw.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ta.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_te.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_tg.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_th.arb | 153 ++++++++++++++++-- packages/smooth_app/lib/l10n/app_ti.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_tl.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_tn.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_tr.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ts.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_tt.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_tw.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ty.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ug.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_uk.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ur.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_uz.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_ve.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_vi.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_wa.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_wo.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_xh.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_yi.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_yo.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_zh.arb | 151 +++++++++++++++-- packages/smooth_app/lib/l10n/app_zu.arb | 151 +++++++++++++++-- 126 files changed, 17345 insertions(+), 1534 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_aa.arb b/packages/smooth_app/lib/l10n/app_aa.arb index fc9236d5844..4c629c401ac 100644 --- a/packages/smooth_app/lib/l10n/app_aa.arb +++ b/packages/smooth_app/lib/l10n/app_aa.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_af.arb b/packages/smooth_app/lib/l10n/app_af.arb index b56bfb1c434..21d0f14f6cb 100644 --- a/packages/smooth_app/lib/l10n/app_af.arb +++ b/packages/smooth_app/lib/l10n/app_af.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ak.arb b/packages/smooth_app/lib/l10n/app_ak.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_ak.arb +++ b/packages/smooth_app/lib/l10n/app_ak.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_am.arb b/packages/smooth_app/lib/l10n/app_am.arb index b926b0b3392..416ed2c77ed 100644 --- a/packages/smooth_app/lib/l10n/app_am.arb +++ b/packages/smooth_app/lib/l10n/app_am.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ar.arb b/packages/smooth_app/lib/l10n/app_ar.arb index e6598148d79..1f9dcc97150 100644 --- a/packages/smooth_app/lib/l10n/app_ar.arb +++ b/packages/smooth_app/lib/l10n/app_ar.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "الفئات", - "edit_ingredients_extrait_ingredients_btn_text": "استخراج المكونات", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "تحديث الصورة", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "تحديث الصورة", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "معطيات", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_as.arb b/packages/smooth_app/lib/l10n/app_as.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_as.arb +++ b/packages/smooth_app/lib/l10n/app_as.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_az.arb b/packages/smooth_app/lib/l10n/app_az.arb index bd69088fb79..7b7b86c1735 100644 --- a/packages/smooth_app/lib/l10n/app_az.arb +++ b/packages/smooth_app/lib/l10n/app_az.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kateqoriyalar", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_be.arb b/packages/smooth_app/lib/l10n/app_be.arb index 78ade5a4d4a..f573d468abb 100644 --- a/packages/smooth_app/lib/l10n/app_be.arb +++ b/packages/smooth_app/lib/l10n/app_be.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "У 2012 годзе\nмы вынайшлі праграму\nдля сумеснага сканавання", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Паколькі нам «стукнула»10 гадоў,\nмы вынаходзім яе\nз нуля!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Працягнуць", "onboarding_welcome_loading_dialog_title": "Загружаецца ваш першы прыклад прадукту", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Вібрацыя і тактыльны водгук", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Запоўніце асноўныя звесткі", "not_implemented_snackbar_text": "Яшчэ не рэалізавана", "category_picker_page_appbar_text": "Катэгорыі", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Абнавіць фота", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Распазнаць упакоўку", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Абнавіць фота", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Даныя", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Выключыць Eco-ацэнку", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bg.arb b/packages/smooth_app/lib/l10n/app_bg.arb index 8630cd5763c..4f79aa0a9fa 100644 --- a/packages/smooth_app/lib/l10n/app_bg.arb +++ b/packages/smooth_app/lib/l10n/app_bg.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Харесваш ли приложението?", "tagline_app_review_button_positive": "Обичам го! 😍", "tagline_app_review_button_negative": "Не особено…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Измислихме приложението\nза съвместно сканиране \nпрез 2012 г.", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "10 години по-късно\nго преоткриваме\nот самото начало!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Продължи", "onboarding_welcome_loading_dialog_title": "Зареждане на първия ти примерен продукт", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Вибрация и усещане", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Попълни основните подробности", "not_implemented_snackbar_text": "Все още не е внедрено", "category_picker_page_appbar_text": "Категории", - "edit_ingredients_extrait_ingredients_btn_text": "Извлечи съставките", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Обнови снимката", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Извличане на опаковката", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Обнови снимката", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Продъктът не е открит", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Данни", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Изключи Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Инсталирай Open Beauty Facts, за да създадеш козметична база данни", "faq_title_install_pet": "Инсталирай Open Pet Food Facts, за да създадеш база данни с храни за домашни любимци", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bm.arb b/packages/smooth_app/lib/l10n/app_bm.arb index e690df2c05f..034656adb48 100644 --- a/packages/smooth_app/lib/l10n/app_bm.arb +++ b/packages/smooth_app/lib/l10n/app_bm.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Suguyaw", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bn.arb b/packages/smooth_app/lib/l10n/app_bn.arb index b527cd8d2f3..df9e896913f 100644 --- a/packages/smooth_app/lib/l10n/app_bn.arb +++ b/packages/smooth_app/lib/l10n/app_bn.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "শ্রেণীসমূহ", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "তথ্য", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bo.arb b/packages/smooth_app/lib/l10n/app_bo.arb index cc484540a5f..d880cf68188 100644 --- a/packages/smooth_app/lib/l10n/app_bo.arb +++ b/packages/smooth_app/lib/l10n/app_bo.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_br.arb b/packages/smooth_app/lib/l10n/app_br.arb index 564fb54b9e9..a47c5ccddb6 100644 --- a/packages/smooth_app/lib/l10n/app_br.arb +++ b/packages/smooth_app/lib/l10n/app_br.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Rummadoù", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Roadennoù", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bs.arb b/packages/smooth_app/lib/l10n/app_bs.arb index a4975f2b013..9f80e3cf392 100644 --- a/packages/smooth_app/lib/l10n/app_bs.arb +++ b/packages/smooth_app/lib/l10n/app_bs.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorije", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ca.arb b/packages/smooth_app/lib/l10n/app_ca.arb index 15cf1ede7d0..cd0811b7bed 100644 --- a/packages/smooth_app/lib/l10n/app_ca.arb +++ b/packages/smooth_app/lib/l10n/app_ca.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Us agrada l'aplicació?", "tagline_app_review_button_positive": "M'encanta! 😍", "tagline_app_review_button_negative": "No gaire…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Vam inventar\nl'aplicació col·laborativa\nd'escaneig l'any 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Ja que en fem 10,\nl'estem reinventant\ndes de zero!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continuar", "onboarding_welcome_loading_dialog_title": "S'està carregant el vostre primer exemple de producte", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibració i hàptica", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Detalls bàsics complets", "not_implemented_snackbar_text": "Encara no s'ha implementat", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extreu els ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Actualitza la foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extreure l'embalatge", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Actualitza la foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Afegir un preu", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "No s'ha trobat el producte", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Preu", "prices_amount_price_discounted": "Preu rebaixat", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Dades", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclou l'Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ce.arb b/packages/smooth_app/lib/l10n/app_ce.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_ce.arb +++ b/packages/smooth_app/lib/l10n/app_ce.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_co.arb b/packages/smooth_app/lib/l10n/app_co.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_co.arb +++ b/packages/smooth_app/lib/l10n/app_co.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cs.arb b/packages/smooth_app/lib/l10n/app_cs.arb index 4283ad9d889..aac58d30cc8 100644 --- a/packages/smooth_app/lib/l10n/app_cs.arb +++ b/packages/smooth_app/lib/l10n/app_cs.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Líbí se vám aplikace?", "tagline_app_review_button_positive": "Miluji to! 😍", "tagline_app_review_button_negative": "Ani ne...", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "V roce 2012 jsme vynalezli\nkooperativní\naplikaci pro skenování", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Jelikož je nám 10 let, vymýšlíme ji od základu znovu!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Pokračovat", "onboarding_welcome_loading_dialog_title": "Načítám váš první příklad produktu", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibrace a haptika", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Vyplňte základní údaje", "not_implemented_snackbar_text": "Zatím neimplementováno", "category_picker_page_appbar_text": "Kategorie", - "edit_ingredients_extrait_ingredients_btn_text": "Aut. rozpoznat složení", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Obnovit fotku", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extrakt balení", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Obnovit fotku", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Zástupce pro aplikaci Ceny na produktové stránce", "prices_app_button": "Přejít do aplikace Ceny", "prices_generic_title": "Ceny", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Přidat cenu", - "prices_send_the_price": "Poslat cenu", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Produkt nebyl nalezen", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Hledat produkt", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "Zobrazit ceny", "prices_list_length_one_page": "{count,plural, =0{Zatím žádná cena} =1{Pouze 1 cena} few{Všechny {count} ceny} other{Všech {count} cen}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Množství", "prices_amount_is_discounted": "Je zlevněné?", "prices_amount_price_normal": "Cena", "prices_amount_price_discounted": "Snížená cena", "prices_amount_price_not_discounted": "Původní cena", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Nesprávná hodnota", "prices_amount_price_mandatory": "Povinná hodnota", "prices_currency_subtitle": "Měna", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Údaje", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Vyloučit Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Znovu použijte a upravte toto vyhledávání", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Moje důkazy", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Přidány nejnovější ceny", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Nainstalujte Open Beauty Facts a vytvořte kosmetickou databázi", "faq_title_install_pet": "Nainstalujte si Open Pet Food Facts a vytvořte databázi krmiv pro domácí zvířata", "faq_title_install_product": "Nainstalujte Open Products Facts pro vytvoření databáze produktů pro prodloužení životnosti objektů", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Importujte své produkty do Open Food Facts", "contact_title_pro_email": "Kontakt výrobce", "contact_title_press_page": "Pro média", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "Co se nemění", "guide_nutriscore_v2_unchanged_paragraph1": "Nutri-Score je skóre navržené k **měření nutriční kvality**. Je **doplňkem skupiny NOVA** pro **ultra zpracované potraviny** (taktéž přítomných v aplikaci).", "guide_nutriscore_v2_unchanged_paragraph2": "Pro výrobce zůstává zobrazení Nutri-Score **nepovinné**.", - "guide_nutriscore_v2_share_link": "https://world-cs.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cv.arb b/packages/smooth_app/lib/l10n/app_cv.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_cv.arb +++ b/packages/smooth_app/lib/l10n/app_cv.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cy.arb b/packages/smooth_app/lib/l10n/app_cy.arb index ac47bed7599..1c3b2975c95 100644 --- a/packages/smooth_app/lib/l10n/app_cy.arb +++ b/packages/smooth_app/lib/l10n/app_cy.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categorïau", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_da.arb b/packages/smooth_app/lib/l10n/app_da.arb index b8ba74d90d4..90bc68b80ec 100644 --- a/packages/smooth_app/lib/l10n/app_da.arb +++ b/packages/smooth_app/lib/l10n/app_da.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Kan du lide appen?", "tagline_app_review_button_positive": "Jeg elsker det! 😍", "tagline_app_review_button_negative": "Ikke rigtigt…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Vi opfandt\nden kollaborative\nskannings-app i 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Da vi fylder 10 år,\nvi genopfinder den\nfra bunden!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Velkommen!", + "onboarding_home_welcome_text2": "Appen, der hjælper dig med at vælge mad, der er godt for **dig** og **planeten**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Fortsæt", "onboarding_welcome_loading_dialog_title": "Indlæser første eksempelprodukt", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration og haptik", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Udfyld basisoplysninger", "not_implemented_snackbar_text": "Endnu ikke implementeret", "category_picker_page_appbar_text": "Kategorier", - "edit_ingredients_extrait_ingredients_btn_text": "Udtræk ingredienser", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Opfrisk foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Udtræk emballage", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Opfrisk foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Produktet blev ikke fundet", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Stregkodelæser", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Undtag Øko-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Genbrug og redigér denne søgning", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "Ny beregning af Nutri-Score: hvad er nyt?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_de.arb b/packages/smooth_app/lib/l10n/app_de.arb index 5c0e7bb2786..9af6a20011c 100644 --- a/packages/smooth_app/lib/l10n/app_de.arb +++ b/packages/smooth_app/lib/l10n/app_de.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Foto aufgenommen am {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Foto aufgenommen am {date}. Dieses Foto kann veraltet sein", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Willkommen bei Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Neueste Nachrichten: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Gefällt Ihnen die App?", "tagline_app_review_button_positive": "Ich liebe sie! 😍", "tagline_app_review_button_negative": "Nicht wirklich …", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Wir haben 2012 die\nApp für kollaboratives\nScannen erfunden", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Anlässlich unseres\n10-jährigen Bestehens\nerfinden wir es von Grund auf neu!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Willkommen!", + "onboarding_home_welcome_text2": "Die App, die Ihnen hilft, Lebensmittel auszuwählen, die gut für **Sie** und den **Planeten** sind!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Weiter", "onboarding_welcome_loading_dialog_title": "Ihr erstes Beispielprodukt wird geladen", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Lesen Sie einen Barcode mit Ihrer Kamera ein", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration und haptisches Feedback", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Allgemeine Angaben vervollständigen", "not_implemented_snackbar_text": "Noch nicht implementiert", "category_picker_page_appbar_text": "Kategorien", - "edit_ingredients_extrait_ingredients_btn_text": "Zutaten extrahieren", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Zutaten aus dem Foto extrahieren", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Zutaten werden aus\ndem Foto extrahiert", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Foto wird geladen …", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Foto aktualisieren", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Verpackung extrahieren", + "edit_packaging_extract_btn_text": "Verpackung aus dem\nFoto extrahieren", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Verpackung wird aus dem Foto extrahiert", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Foto wird geladen …", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Foto aktualisieren", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Verknüpfung zur Preise-App auf der Produktseite", "prices_app_button": "Zur Preise-App wechseln", "prices_generic_title": "Preise", + "prices_add_n_prices": "{count,plural, one {}=1{Preis hinzufügen} other{{count} Preise hinzufügen}}", + "prices_send_n_prices": "{count,plural, one {}=1{Preis senden} other{{count} Preise senden}}", + "prices_add_an_item": "Ein Element hinzufügen", "prices_add_a_price": "Preis hinzufügen", - "prices_send_the_price": "Preis senden", + "prices_add_a_receipt": "Beleg hinzufügen", + "prices_add_price_tags": "Preisschilder hinzufügen", + "prices_barcode_search_not_found": "Produkt nicht gefunden", + "prices_barcode_search_none_yet": "Noch kein Produkt", + "prices_barcode_search_question": "Möchten Sie nach diesem Produkt suchen?", + "prices_barcode_search_title": "Produkte suchen", + "prices_barcode_search_running": "Nach {barcode} suchen", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcodelesegerät", "prices_view_prices": "Preise anzeigen", "prices_list_length_one_page": "{count,plural, =0{Noch kein Preis} =1{Nur ein Preis} other{Alle {count} Preise}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, one {}=0{Noch kein Nachweis} =1{Nur ein Nachweis} other{Alle {count} Nachweise}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Letzte {pageSize} Nachweise (insgesamt: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Die besten {pageSize} Mitwirkende (insgesamt: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Betrag", "prices_amount_is_discounted": "Preisreduziert?", "prices_amount_price_normal": "Preis", "prices_amount_price_discounted": "Reduzierter Preis", "prices_amount_price_not_discounted": "Ursprünglicher Preis", + "prices_amount_no_product": "Ein Produkt fehlt!", "prices_amount_price_incorrect": "Ungültiger Wert", "prices_amount_price_mandatory": "Notwendiger Wert", "prices_currency_subtitle": "Währung", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Serverkonfiguration", + "dev_mode_section_product_page": "Produktseite", + "dev_mode_section_ui": "Benutzeroberfläche", + "dev_mode_section_data": "Daten", + "dev_mode_section_experimental_features": "Experimentelle Funktionen", "dev_mode_hide_ecoscore_title": "Eco-Score ausschließen", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Verwenden Sie eine Rechtschreibprüfung für OCR-Bildschirme", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Zutaten und Verpackung)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Diese Suche wiederverwenden und bearbeiten", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Meine Belege", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "Meine Nachweise", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Preise der Mitwirkenden", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Neueste Preise hinzugefügt", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Installieren Sie Open Beauty Facts, um eine Kosmetikdatenbank zu erstellen", "faq_title_install_pet": "Installieren Sie Open Pet Food Facts, um eine Tierfutterdatenbank zu erstellen", "faq_title_install_product": "Installieren Sie Open Products Facts, um eine Produktdatenbank zur Verlängerung der Lebensdauer von Objekten zu erstellen", + "faq_nutriscore_nutriscore": "Neue Berechnung des Nutri-Score: Was ist neu?", "contact_title_pro_page": "Pro? Importieren Sie Ihre Produkte in Open Food Facts", "contact_title_pro_email": "Kontakt zum Produzenten", "contact_title_press_page": "Pressemappe", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "Was sich nicht ändert", "guide_nutriscore_v2_unchanged_paragraph1": "Der Nutri-Score ist ein Punktesystem zur **Bewertung der Nährwertqualität**. Er ist eine **Ergänzung zur NOVA-Gruppe** für **hochverarbeitete Lebensmittel** (ebenfalls in der App enthalten).", "guide_nutriscore_v2_unchanged_paragraph2": "Für die Hersteller ist die Angabe des Nutri-Score **weiterhin optional**.", - "guide_nutriscore_v2_share_link": "https://de.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://de.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Vorschau", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_el.arb b/packages/smooth_app/lib/l10n/app_el.arb index 35df409be5d..5a60a511338 100644 --- a/packages/smooth_app/lib/l10n/app_el.arb +++ b/packages/smooth_app/lib/l10n/app_el.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Σχεδιάσαμε\nτη συλλογική εφαρμογή σάρωσης\nτο 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Καθώς κλείνουμε τα 10, επανασχεδιάζουμε την εφαρμογή ξανά\nαπό την αρχή!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Φόρτωση του πρώτου παραδείγματος προϊόντος σας", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Συμπληρώστε τις βασικές λεπτομέρειες", "not_implemented_snackbar_text": "Δεν έχει υλοποιηθεί ακόμη", "category_picker_page_appbar_text": "Κατηγορίες", - "edit_ingredients_extrait_ingredients_btn_text": "Εξαγωγή συστατικών", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Ανανέωση φωτογραφίας", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Ανανέωση φωτογραφίας", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Δεδομένα", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 11fb0307a4e..b083ea0a688 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1122,7 +1122,7 @@ "onboarding_home_welcome_text1": "Welcome !", "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", "@onboarding_home_welcome_text2": { - "description": "Onboarding home screen welcome text, text surrounded by * will be bold" + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", @@ -2941,4 +2941,4 @@ "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } -} +} \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eo.arb b/packages/smooth_app/lib/l10n/app_eo.arb index 75484597950..4b83b9f54aa 100644 --- a/packages/smooth_app/lib/l10n/app_eo.arb +++ b/packages/smooth_app/lib/l10n/app_eo.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorioj", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_es.arb b/packages/smooth_app/lib/l10n/app_es.arb index 8c89f123f2f..83aba39111e 100644 --- a/packages/smooth_app/lib/l10n/app_es.arb +++ b/packages/smooth_app/lib/l10n/app_es.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Bienvenida a Open Food Facts∫", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "¿Te gusta la aplicación?", "tagline_app_review_button_positive": "¡Me encanta! 😍", "tagline_app_review_button_negative": "No mucho…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Inventamos\nla aplicación de escaneo\ncolaborativa en 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Hemos cumplido 10 años\ny nos estamos reinventando\n¡por completo!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continuar", "onboarding_welcome_loading_dialog_title": "Cargando tu primer producto de ejemplo", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibración y respuesta táctil", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Completa los detalles básicos", "not_implemented_snackbar_text": "Aún sin implementar", "category_picker_page_appbar_text": "Categorías", - "edit_ingredients_extrait_ingredients_btn_text": "Extraer ingredientes", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Actualizar foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extraer el envase", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Actualizar foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Acceso directo a la aplicación Prices en la página del producto", "prices_app_button": "Ir a la aplicación Prices", "prices_generic_title": "Precios", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Añadir un precio", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Producto no encontrado", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Búsqueda de producto", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Precio", "prices_amount_price_discounted": "Precio con descuento", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Moneda", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Datos", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Excluir Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reutilizar y editar esta búsqueda", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Mis pruebas", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Instala Open Beauty Facts para crear una base de datos sobre cosmética", "faq_title_install_pet": "Instala Open Pet Food Facts para crear una base de datos sobre alimentación para mascotas", "faq_title_install_product": "Instala Open Products Facts para crear una base de datos sobre productos del día a día", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "¿Eres profesional? Importa tus productos a Open Food Facts", "contact_title_pro_email": "Contacto para productores", "contact_title_press_page": "Página de prensa", @@ -2740,5 +2863,9 @@ "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_et.arb b/packages/smooth_app/lib/l10n/app_et.arb index 5cd3d6180cf..050e4ce7d3c 100644 --- a/packages/smooth_app/lib/l10n/app_et.arb +++ b/packages/smooth_app/lib/l10n/app_et.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategooriad", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Andmed", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eu.arb b/packages/smooth_app/lib/l10n/app_eu.arb index a0b4ee778c5..594021bf777 100644 --- a/packages/smooth_app/lib/l10n/app_eu.arb +++ b/packages/smooth_app/lib/l10n/app_eu.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Aplikazioa gustatzen zaizu?", "tagline_app_review_button_positive": "Datsegit! 😍", "tagline_app_review_button_negative": "Egia esan ez…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategoriak", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Prezioak aplikazioko produktuaren orrirako laster-bidea", "prices_app_button": "Joan Prezioak aplikaziora", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Deskontua egindako prezioa", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Datuak", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Berrerabili eta editatu bilaketa hau", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fa.arb b/packages/smooth_app/lib/l10n/app_fa.arb index 1170cdd8a82..389afe3a5b9 100644 --- a/packages/smooth_app/lib/l10n/app_fa.arb +++ b/packages/smooth_app/lib/l10n/app_fa.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "دسته‌‎بندی‎ها", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fi.arb b/packages/smooth_app/lib/l10n/app_fi.arb index 093100ca924..26cf7e07dbf 100644 --- a/packages/smooth_app/lib/l10n/app_fi.arb +++ b/packages/smooth_app/lib/l10n/app_fi.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Pidätkö sovelluksesta?", "tagline_app_review_button_positive": "Rakastan sitä! 😍", "tagline_app_review_button_negative": "En juurikaan…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Teimme\nyhteisöllisen\nlukijasovelluksen vuonna 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Täyttäessämme 10\nuudistamme sitä\nalusta alkaen.", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Jatka", "onboarding_welcome_loading_dialog_title": "Ladataan ensimmäistä esimerkkituotettasi", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Värinä ja haptiikka", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Täytä perustiedot", "not_implemented_snackbar_text": "Ei vielä käytössä", "category_picker_page_appbar_text": "Tuoteluokat", - "edit_ingredients_extrait_ingredients_btn_text": "Poimi ainesosat", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Päivitä kuva", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Pura pakkaus", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Päivitä kuva", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Pikakuvake Hinnat-sovellukseen tuotesivulla", "prices_app_button": "Siirry Hinnat-sovellukseen", "prices_generic_title": "Hinnat", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Lisää hinta", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Tuotetta ei löytynyt", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Tuotehaku", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Hinta", "prices_amount_price_discounted": "Alennettu hinta", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Valuutta", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Tiedot", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Jätä ympäristöystävällisyyspisteytys huomiotta", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Käytä ja muokkaa tätä hakua uudelleen", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Minun todisteeni", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Luo kosmeettinen tietokanta asentamalla Open Beauty Facts", "faq_title_install_pet": "Luo lemmikkieläinten ruokatietokanta asentamalla Open Pet Food Facts", "faq_title_install_product": "Asenna Open Products Facts luodaksesi tuotetietokannan objektien käyttöiän pidentämiseksi", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Tuo tuotteesi Open Food Factsiin", "contact_title_pro_email": "Tuottajan yhteystiedot", "contact_title_press_page": "Lehdistösivu", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fo.arb b/packages/smooth_app/lib/l10n/app_fo.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_fo.arb +++ b/packages/smooth_app/lib/l10n/app_fo.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 92aa57cbeea..4e9ae8dd5b9 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image prise le {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image prise le {date}. Cette image est peut-être obsolète", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Bienvenue sur Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Aimez-vous cette appli ?", "tagline_app_review_button_positive": "Je l'adore! 😍", "tagline_app_review_button_negative": "Pas vraiment…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Nous avons inventé\nl'appli de scan\ncollaborative en 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "10 ans après,\nnous la réinventons\ncomplètement !", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Bienvenue !", + "onboarding_home_welcome_text2": "L'application qui vous aide à choisir de la nourriture qui est bonne pour **vous** et la **planète** !", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continuer", "onboarding_welcome_loading_dialog_title": "Chargement de votre premier exemple de produit", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration et retours tactiles", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,10 +1479,18 @@ "completed_basic_details_btn_text": "Compléter les informations de base", "not_implemented_snackbar_text": "Pas encore disponible", "category_picker_page_appbar_text": "Catégories", - "edit_ingredients_extrait_ingredients_btn_text": "Extraire les ingrédients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extraire les ingrédients à partir de la photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extraction des ingrédients à partir de la photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Chargement de la photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Mettre à jour la photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1462,6 +1499,14 @@ "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extraction de l'emballage à partir de la photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Chargement de la photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Mettre à jour la photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1778,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Configuration du serveur", + "dev_mode_section_product_page": "Page produit", + "dev_mode_section_ui": "Interface utilisateur", + "dev_mode_section_data": "Données", + "dev_mode_section_experimental_features": "Fonctionnalités expérimentales", "dev_mode_hide_ecoscore_title": "Exclure l'éco-score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Réutiliser et modifier cette recherche", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -2713,6 +2771,7 @@ "faq_title_install_beauty": "Installez Open Beauty Facts pour créer une base de données cosmétiques", "faq_title_install_pet": "Installez Open Pet Food Facts pour créer une base de données sur les aliments pour animaux de compagnie", "faq_title_install_product": "Installez Open Products Facts pour créer une base de données de produits afin de prolonger la durée de vie des objets", + "faq_nutriscore_nutriscore": "Nouveau calcul du Nutri-Score : qu'est-ce qui a changé ?", "contact_title_pro_page": "Pro? Importez vos produits dans Open Food Facts", "contact_title_pro_email": "Contact producteur", "contact_title_press_page": "Page de presse", @@ -2764,7 +2823,7 @@ "@guide_nutriscore_v2_title": { "description": "The title of the guide (please don't forget the use of non-breaking spaces)" }, - "guide_nutriscore_v2_file_language": "en", + "guide_nutriscore_v2_file_language": "fr", "@guide_nutriscore_v2_file_language": { "description": "The logo is only available in de/en/fr/ln/nl. Please use en if not available (in lowercase, please)." }, @@ -2804,5 +2863,9 @@ "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Aperçu", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } -} +} \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ga.arb b/packages/smooth_app/lib/l10n/app_ga.arb index f917571b8e9..326ba962b9a 100644 --- a/packages/smooth_app/lib/l10n/app_ga.arb +++ b/packages/smooth_app/lib/l10n/app_ga.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Catagóirí", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gd.arb b/packages/smooth_app/lib/l10n/app_gd.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_gd.arb +++ b/packages/smooth_app/lib/l10n/app_gd.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gl.arb b/packages/smooth_app/lib/l10n/app_gl.arb index 8d8d6f64392..820ec0df6e8 100644 --- a/packages/smooth_app/lib/l10n/app_gl.arb +++ b/packages/smooth_app/lib/l10n/app_gl.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categorías", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Datos", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gu.arb b/packages/smooth_app/lib/l10n/app_gu.arb index 47715b00b12..1ab5d8c7a32 100644 --- a/packages/smooth_app/lib/l10n/app_gu.arb +++ b/packages/smooth_app/lib/l10n/app_gu.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "શ્રેણીઓ", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "માહિતી", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ha.arb b/packages/smooth_app/lib/l10n/app_ha.arb index d2d3c892b1e..26d87af487c 100644 --- a/packages/smooth_app/lib/l10n/app_ha.arb +++ b/packages/smooth_app/lib/l10n/app_ha.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index 87ae2b151f8..c4ea97f5154 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "התמונה צולמה ב־{date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "התמונה צולמה ב־{date}. היא כנראה לא עדכנית", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "ברוך בואך ל־Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "איך היישומון שלנו?", "tagline_app_review_button_positive": "הוא מעולה! 😍", "tagline_app_review_button_negative": "ככה ככה…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "המצאנו\nאת יישומון\nהסריקה השיתופי ב־2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "לרגל יום ההולדת\nהעשירי אנחנו מחדשים\nאותו לגמרי מאפס!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "להמשיך", "onboarding_welcome_loading_dialog_title": "מוצר ההדגמה הראשוני שלך נטען", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "רטט ומשוב פיזי", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "השלמת הפרטים הבסיסיים", "not_implemented_snackbar_text": "לא מיושם עדיין", "category_picker_page_appbar_text": "קטגוריות", - "edit_ingredients_extrait_ingredients_btn_text": "חילוץ רכיבים", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "רענון תמונה", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "חילוץ אריזה", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "רענון תמונה", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "קיצור דרך ליישומון מחירים בעמוד המוצר", "prices_app_button": "מעבר ליישומון המחירים", "prices_generic_title": "מחירים", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "הוספת מחיר", - "prices_send_the_price": "שליחת המחיר", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "המוצר לא נמצא", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "חיפוש מוצרים", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, two {כל {count} המחירים} many {כל {count} המחירים}=0{אין מחיר עדיין} =1{מחיר אחד בלבד} other{כל {count} המחירים}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "{pageSize} המתנדבים המובילים (בסך הכול: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "סכום", "prices_amount_is_discounted": "בהנחה?", "prices_amount_price_normal": "מחיר", "prices_amount_price_discounted": "מחיר מוזל", "prices_amount_price_not_discounted": "מחיר מקורי", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "ערך שגוי", "prices_amount_price_mandatory": "ערך חובה", "prices_currency_subtitle": "מטבע", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "נתונים", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "להחריג Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "שימוש בחיפוש ועריכתו", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "ההוכחות שלי", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "מחירי מתנדבים", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "המחירים האחרים שנוספו", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "אפשר להתקין את Open Beauty Facts כדי ליצור מסד נתונים קוסמטי", "faq_title_install_pet": "אפשר להתקין את Open Pet Food Facts כדי ליצור מסד נתוני מזון לחיות מחמד", "faq_title_install_product": "אפשר להתקין את Open Products Facts כדי ליצור מסד נתונים של מוצרים להארכת חיי הפריטים", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "יצרנים? אפשר לייבא את המוצרים שלכם ל־Open Food Facts", "contact_title_pro_email": "איש קשר ליצרנים", "contact_title_press_page": "עמוד לעיתונאים", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "מה לא משתנה", "guide_nutriscore_v2_unchanged_paragraph1": "Nutri-Score הוא ציון שנועד **למדוד איכות תזונתית**. הוא **משלים לקבוצת NOVA** על **מזון אולטרה מעובד** (קיים גם ביישום).", "guide_nutriscore_v2_unchanged_paragraph2": "ליצרנים, התצוגה של Nutri-Score **נותרת בגדר רשות**.", - "guide_nutriscore_v2_share_link": "https://il.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hi.arb b/packages/smooth_app/lib/l10n/app_hi.arb index 7e6539d53c8..a1f35fb3f93 100644 --- a/packages/smooth_app/lib/l10n/app_hi.arb +++ b/packages/smooth_app/lib/l10n/app_hi.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "श्रेणियाँ", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "एक मूल्य जोड़े", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "कीमत", "prices_amount_price_discounted": "छूट की दर", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "जानकारी", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hr.arb b/packages/smooth_app/lib/l10n/app_hr.arb index f15940835c8..0c4bb37ef9e 100644 --- a/packages/smooth_app/lib/l10n/app_hr.arb +++ b/packages/smooth_app/lib/l10n/app_hr.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorije", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Podaci", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ht.arb b/packages/smooth_app/lib/l10n/app_ht.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_ht.arb +++ b/packages/smooth_app/lib/l10n/app_ht.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hu.arb b/packages/smooth_app/lib/l10n/app_hu.arb index b5e54b03381..9854b5b93cb 100644 --- a/packages/smooth_app/lib/l10n/app_hu.arb +++ b/packages/smooth_app/lib/l10n/app_hu.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategóriák", - "edit_ingredients_extrait_ingredients_btn_text": "Összetevők kiolvasása", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Adatok", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hy.arb b/packages/smooth_app/lib/l10n/app_hy.arb index 9f9951c5877..d7770356fdc 100644 --- a/packages/smooth_app/lib/l10n/app_hy.arb +++ b/packages/smooth_app/lib/l10n/app_hy.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_id.arb b/packages/smooth_app/lib/l10n/app_id.arb index b99b5748e35..96d58d02f4d 100644 --- a/packages/smooth_app/lib/l10n/app_id.arb +++ b/packages/smooth_app/lib/l10n/app_id.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Suka dengan aplikasinya?", "tagline_app_review_button_positive": "Saya suka sekali! 😍", "tagline_app_review_button_negative": "Tidak begitu…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Kami membuat\naplikasi pemindaian\nkolaboratif ini pada tahun 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Saat kami berusia 10 tahun,\nkami menciptakannya lagi\ndari awal!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Selanjutnya", "onboarding_welcome_loading_dialog_title": "Memuat produk contoh pertama Anda", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Getaran & Haptik", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Lengkapi informasi dasar", "not_implemented_snackbar_text": "Belum diimplementasi", "category_picker_page_appbar_text": "Kategori", - "edit_ingredients_extrait_ingredients_btn_text": "Ekstrak kandungan bahan", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Muat ulang foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Kemasan ekstrak", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Muat ulang foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Pintasan ke aplikasi Harga di halaman produk", "prices_app_button": "Buka aplikasi Harga", "prices_generic_title": "Harga", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Tambahkan harga", - "prices_send_the_price": "Kirim harga", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Produk tidak ditemukan", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Pencarian produk", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "Lihat harga", "prices_list_length_one_page": "{count,plural, =0{Belum ada harga} =1{Hanya satu harga} other{Semua {count} harga}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Jumlah", "prices_amount_is_discounted": "Apakah didiskon?", "prices_amount_price_normal": "Harga", "prices_amount_price_discounted": "Harga sesudah diskon", "prices_amount_price_not_discounted": "Harga asli", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Nilai tidak valid", "prices_amount_price_mandatory": "Nilai wajib", "prices_currency_subtitle": "Mata uang", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Kecualikan Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Gunakan kembali dan sunting pencarian ini", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Bukti saya", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Instal Open Beauty Facts untuk membuat basis data kosmetik", "faq_title_install_pet": "Instal Open Pet Food Facts untuk membuat basis data makanan hewan peliharaan", "faq_title_install_product": "Instal Open Products Facts untuk membuat basis data produk guna memperpanjang masa pakai objek", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Impor produk Anda di Open Food Facts", "contact_title_pro_email": "Kontak Produser", "contact_title_press_page": "Halaman Pers", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "Apa yang tidak berubah", "guide_nutriscore_v2_unchanged_paragraph1": "Nutri-Score merupakan skor yang dirancang untuk **mengukur kualitas nutrisi**. Ini **melengkapi klasifikasi grup NOVA** untuk **makanan ultra proses** (yang juga ada di dalam aplikasi).", "guide_nutriscore_v2_unchanged_paragraph2": "Bagi produsen, tampilan Nutri-Score **tetap opsional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ii.arb b/packages/smooth_app/lib/l10n/app_ii.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_ii.arb +++ b/packages/smooth_app/lib/l10n/app_ii.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_is.arb b/packages/smooth_app/lib/l10n/app_is.arb index 3cb38de7b05..9fe368ece44 100644 --- a/packages/smooth_app/lib/l10n/app_is.arb +++ b/packages/smooth_app/lib/l10n/app_is.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_it.arb b/packages/smooth_app/lib/l10n/app_it.arb index d7ddf0440f9..2492bb195b3 100644 --- a/packages/smooth_app/lib/l10n/app_it.arb +++ b/packages/smooth_app/lib/l10n/app_it.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Immagine acquisita in data {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Immagine acquisita in data {date}. Questa immagine potrebbe essere obsoleta", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Benvenuti in Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Ti piace l'app?", "tagline_app_review_button_positive": "La adoro! 😍", "tagline_app_review_button_negative": "Non proprio…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Abbiamo inventato\nl'app di scansione collaborativa\nnel 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Mentre giriamo 10,\nlo stiamo reinventando\nda zero!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Benvenuto !", + "onboarding_home_welcome_text2": "L'app che ti aiuta a scegliere il cibo che fa bene a **te** e al **pianeta**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continua", "onboarding_welcome_loading_dialog_title": "Caricamento del tuo primo prodotto d'esempio", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibrazione e Tatto", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Completa i dettagli di base", "not_implemented_snackbar_text": "Non ancora implementato", "category_picker_page_appbar_text": "Categorie", - "edit_ingredients_extrait_ingredients_btn_text": "Estrai ingredienti", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Estrai gli ingredienti dalla foto", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Estrazione degli ingredienti\ndalla foto", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Caricamento della foto…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Aggiorna foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Estrarre la confezione", + "edit_packaging_extract_btn_text": "Estrai la confezione\ndalla foto", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Estrazione della confezione dalla foto", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Caricamento della foto…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Aggiorna foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Collegamento all'app Prezzi sulla pagina del prodotto", "prices_app_button": "Vai all'app Prezzi", "prices_generic_title": "Prezzi", + "prices_add_n_prices": "{count,plural, one {}=1{Aggiungi un prezzo} other{Aggiungi {count} prezzi}}", + "prices_send_n_prices": "{count,plural, =1{Invia il prezzo} other{Invia {count} prezzi}}", + "prices_add_an_item": "Aggiungi un elemento", "prices_add_a_price": "Aggiungi un prezzo", - "prices_send_the_price": "Invia il prezzo", + "prices_add_a_receipt": "Aggiungi una ricevuta", + "prices_add_price_tags": "Aggiungi prezzi", + "prices_barcode_search_not_found": "Prodotto non trovato", + "prices_barcode_search_none_yet": "Ancora nessun prodotto", + "prices_barcode_search_question": "Vuoi cercare questo prodotto?", + "prices_barcode_search_title": "Ricerca prodotti", + "prices_barcode_search_running": "Ricerca del codice a barre {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Lettore del codice a barre", "prices_view_prices": "Guarda i prezzi", "prices_list_length_one_page": "{count,plural, =0{Ancora nessun prezzo} =1{Solo un prezzo} other{Tutti e {count} i prezzi}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{Ancora nessuna prova} =1{Solo una prova} other{Tutte e {count} le prove}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Ultime {pageSize} prove (totale: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Principali {pageSize} contributori (totali: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Quantità", "prices_amount_is_discounted": "È scontato?", "prices_amount_price_normal": "Prezzo", "prices_amount_price_discounted": "Prezzo scontato", "prices_amount_price_not_discounted": "Prezzo originale", + "prices_amount_no_product": "Manca un prodotto!", "prices_amount_price_incorrect": "Valore non corretto", "prices_amount_price_mandatory": "Valore obbligatorio", "prices_currency_subtitle": "Moneta", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Configurazione del server", + "dev_mode_section_product_page": "Pagina del prodotto", + "dev_mode_section_ui": "Interfaccia utente", + "dev_mode_section_data": "Dati", + "dev_mode_section_experimental_features": "Funzionalità sperimentali", "dev_mode_hide_ecoscore_title": "Escludi Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Riutilzza e modifica questa ricerca", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Le mie prove", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "La mia prova", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Prezzi dei contributori", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Ultimi prezzi aggiunti", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Installa Open Beauty Facts per creare un database cosmetico", "faq_title_install_pet": "Installa Open Pet Food Facts per creare un database di alimenti per animali domestici", "faq_title_install_product": "Installa Open Products Facts per creare un database di prodotti per prolungare la vita degli oggetti", + "faq_nutriscore_nutriscore": "Nuovo calcolo del Nutri-Score: cosa c'è di nuovo?", "contact_title_pro_page": "Pro? Importa i tuoi prodotti in Open Food Facts", "contact_title_pro_email": "Contatto Produttore", "contact_title_press_page": "Pagina ufficio stampa", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "Cosa non cambia", "guide_nutriscore_v2_unchanged_paragraph1": "Il Nutri-Score è un punteggio progettato per **misurare la qualità nutrizionale**. È **complementare al gruppo NOVA** sugli **alimenti ultra-trasformati** (anch'esso presente nell'applicazione).", "guide_nutriscore_v2_unchanged_paragraph2": "Per i produttori, l'esposizione del Nutri-Score **rimane facoltativa**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Anteprima", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_iu.arb b/packages/smooth_app/lib/l10n/app_iu.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_iu.arb +++ b/packages/smooth_app/lib/l10n/app_iu.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ja.arb b/packages/smooth_app/lib/l10n/app_ja.arb index 3584f7ab9c8..1bfa02af466 100644 --- a/packages/smooth_app/lib/l10n/app_ja.arb +++ b/packages/smooth_app/lib/l10n/app_ja.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "アプリを気に入っていただけましたか?", "tagline_app_review_button_positive": "大好きです! 😍", "tagline_app_review_button_negative": "そうでもないんですが...", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "2012年に\n協同スキャンアプリを\n開発しました", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "10周年に合わせて\n一からアプリを\n再開発しています!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "続ける", "onboarding_welcome_loading_dialog_title": "最初の見本となる製品を読み込んでいます", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "振動と触覚フィードバック", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "基本情報を完成させる", "not_implemented_snackbar_text": "まだ実装されていません", "category_picker_page_appbar_text": "カテゴリー", - "edit_ingredients_extrait_ingredients_btn_text": "原材料を抽出", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "画像を更新", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "パッケージ情報を抽出", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "画像を更新", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "製品ページの価格アプリへのショートカット", "prices_app_button": "価格アプリに移動", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "割引価格", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "サーバー設定", + "dev_mode_section_product_page": "製品ページ", + "dev_mode_section_ui": "ユーザインタフェース", + "dev_mode_section_data": "データ", + "dev_mode_section_experimental_features": "試験的な機能", "dev_mode_hide_ecoscore_title": "Eco-Scoreを無効にする", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "この検索を再利用して編集する", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "自分の証拠", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Open Beauty Facts をインストールして化粧品データベースを作成する", "faq_title_install_pet": "Open Pet Food Facts をインストールしてペットフード データベースを作成する", "faq_title_install_product": "Open Products Facts をインストールして製品データベースを作成し、オブジェクトの寿命を延ばす", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "プロ? Open Food Facts に製品をインポートします", "contact_title_pro_email": "プロデューサー連絡先", "contact_title_press_page": "プレスページ", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "プレビュー", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_jv.arb b/packages/smooth_app/lib/l10n/app_jv.arb index 56ca0f1584a..6c4b65f2656 100644 --- a/packages/smooth_app/lib/l10n/app_jv.arb +++ b/packages/smooth_app/lib/l10n/app_jv.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ka.arb b/packages/smooth_app/lib/l10n/app_ka.arb index 85ec8e4d05d..f1dc68c9413 100644 --- a/packages/smooth_app/lib/l10n/app_ka.arb +++ b/packages/smooth_app/lib/l10n/app_ka.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "მონაცემები", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kk.arb b/packages/smooth_app/lib/l10n/app_kk.arb index ee5b43b45b0..31602b9438c 100644 --- a/packages/smooth_app/lib/l10n/app_kk.arb +++ b/packages/smooth_app/lib/l10n/app_kk.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Санаттар", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Деректер", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_km.arb b/packages/smooth_app/lib/l10n/app_km.arb index 4b19099e5ea..781be4d126e 100644 --- a/packages/smooth_app/lib/l10n/app_km.arb +++ b/packages/smooth_app/lib/l10n/app_km.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kn.arb b/packages/smooth_app/lib/l10n/app_kn.arb index 5f4ee94aaa3..e6acc91c335 100644 --- a/packages/smooth_app/lib/l10n/app_kn.arb +++ b/packages/smooth_app/lib/l10n/app_kn.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "ವರ್ಗಗಳು", - "edit_ingredients_extrait_ingredients_btn_text": "ಪದಾರ್ಥಗಳನ್ನು ಹೊರತೆಗೆಯಿರಿ", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ko.arb b/packages/smooth_app/lib/l10n/app_ko.arb index 6f055403dc5..c0f68d34417 100644 --- a/packages/smooth_app/lib/l10n/app_ko.arb +++ b/packages/smooth_app/lib/l10n/app_ko.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "이 앱이 마음에 드시나요?", "tagline_app_review_button_positive": "최고에요! 😍", "tagline_app_review_button_negative": "별로...", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "2012년에\n협업을 위한\n스캔 앱을 개발했습니다", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "10년이 되어감에 따라,\n스캔 앱을 처음부터\n다시 개발해나가고 있습니다!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "계속하기", "onboarding_welcome_loading_dialog_title": "첫 예시 상품 불러오는 중", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "진동 및 햅틱", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "기본 세부 정보 완성", "not_implemented_snackbar_text": "아직 구현되지 않았어요", "category_picker_page_appbar_text": "카테고리", - "edit_ingredients_extrait_ingredients_btn_text": "성분 추출", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "사진 새로고침", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "포장 사진에서 추출", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "사진 새로고침", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "데이터", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "EcoScore 제외", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ku.arb b/packages/smooth_app/lib/l10n/app_ku.arb index 0ac92e3ce84..22cdd3a1ecb 100644 --- a/packages/smooth_app/lib/l10n/app_ku.arb +++ b/packages/smooth_app/lib/l10n/app_ku.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Vebir", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Dane", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kw.arb b/packages/smooth_app/lib/l10n/app_kw.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_kw.arb +++ b/packages/smooth_app/lib/l10n/app_kw.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ky.arb b/packages/smooth_app/lib/l10n/app_ky.arb index b60cf8e08f7..e25dd64a1fc 100644 --- a/packages/smooth_app/lib/l10n/app_ky.arb +++ b/packages/smooth_app/lib/l10n/app_ky.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_la.arb b/packages/smooth_app/lib/l10n/app_la.arb index 095aa29de7b..46f1db800b4 100644 --- a/packages/smooth_app/lib/l10n/app_la.arb +++ b/packages/smooth_app/lib/l10n/app_la.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lb.arb b/packages/smooth_app/lib/l10n/app_lb.arb index b0e94484ec8..ccb380f1be2 100644 --- a/packages/smooth_app/lib/l10n/app_lb.arb +++ b/packages/smooth_app/lib/l10n/app_lb.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorien", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Daten", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lo.arb b/packages/smooth_app/lib/l10n/app_lo.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_lo.arb +++ b/packages/smooth_app/lib/l10n/app_lo.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lt.arb b/packages/smooth_app/lib/l10n/app_lt.arb index 7ef03f6bdff..bb1e3be0bcf 100644 --- a/packages/smooth_app/lib/l10n/app_lt.arb +++ b/packages/smooth_app/lib/l10n/app_lt.arb @@ -68,15 +68,15 @@ "@unknown": { "description": "Short label for product list view: the compatibility of that product with your preferences is unknown" }, - "match_very_good": "Labai geras atitikimas", + "match_very_good": "Puikus atitikmuo", "@match_very_good": { "description": "Label for product page regarding product compatibility with the user preferences: very good match" }, - "match_good": "Geras atitikimas", + "match_good": "Geras atitikmuo", "@match_good": { "description": "Label for product page regarding product compatibility with the user preferences: good match" }, - "match_poor": "Blogas atitikimas", + "match_poor": "Prastas atitikmuo", "@match_poor": { "description": "Label for product page regarding product compatibility with the user preferences: poor match" }, @@ -88,19 +88,19 @@ "@match_does_not": { "description": "Label for product page regarding product compatibility with the user preferences: does not match" }, - "match_unknown": "Nežinomas pasirinkimas", + "match_unknown": "Nežinomas atitikmuo", "@match_unknown": { "description": "Label for product page regarding product compatibility with the user preferences: unknown match" }, - "match_short_very_good": "Labai geras atitikimas", + "match_short_very_good": "Puikus atitikmuo", "@match_short_very_good": { "description": "Short label for product list view regarding product compatibility with the user preferences: very good match" }, - "match_short_good": "Geras atitikimas", + "match_short_good": "Geras atitikmuo", "@match_short_good": { "description": "Short label for product list view regarding product compatibility with the user preferences: good match" }, - "match_short_poor": "Blogas atitikimas", + "match_short_poor": "Prastas atitikmuo", "@match_short_poor": { "description": "Short label for product list view regarding product compatibility with the user preferences: poor match" }, @@ -112,7 +112,7 @@ "@match_short_does_not": { "description": "Short label for product list view regarding product compatibility with the user preferences: does not match" }, - "match_short_unknown": "Nežinomas pasirinkimas", + "match_short_unknown": "Nežinomas atitikmuo", "@match_short_unknown": { "description": "Short label for product list view regarding product compatibility with the user preferences: unknown match" }, @@ -125,7 +125,7 @@ "@Introduction screen": {}, "welcomeToOpenFoodFacts": "Sveiki atvykę į Open Food Facts", "@welcomeToOpenFoodFacts": {}, - "whatIsOff": "Open Food Facts is a global non-profit powered by local communities.", + "whatIsOff": "„Open Food Facts“ yra pasaulinė ne pelno siekianti organizacija, kurios veiklą skatina vietos bendruomenės.", "@whatIsOff": { "description": "Description of Open Food Facts organization." }, @@ -145,11 +145,11 @@ "@ecoCardUtility": { "description": "Description of what a user can use the Eco data in a product for." }, - "server_error_open_new_issue": "No server response! You may open an issue with the following link.", + "server_error_open_new_issue": "Serveris nepasiekimas! Galite iškelti problemą naudodami šią nuorodą.", "@user_management": {}, - "sign_in_text": "Sign in to your Open Food Facts account to save your contributions", + "sign_in_text": "Prisijunkite prie „Open Food Facts“ paskyros, kad jūsų įneštas savanoriškas indėlis būtų išsaugotas", "incorrect_credentials": "Neteisingas prisijungimo vardas arba slaptažodis.", - "password_lost_incorrect_credentials": "This email or username doesn't exist. Please check your credentials.", + "password_lost_incorrect_credentials": "Šis el. pašto adresas arba naudotojo vardas neegzistuoja. Patikrinkite savo prisijungimo duomenis.", "password_lost_server_unavailable": "We are currently experiencing slowdowns on our servers and we apologise for it. Please try again later.", "login": "Prisijungti", "@login": { @@ -297,7 +297,7 @@ "@darkmode_system_default": { "description": "Indicator inside the darkmode switch (system default)" }, - "thanks_for_contributing": "Thanks for contributing!", + "thanks_for_contributing": "Ačiū, kad prisidėjote!", "contributors_label": "Jie kuria programėlę", "@contributors_label": { "description": "Button label: Opens a pop up window where all contributors of this app are shown" @@ -332,7 +332,7 @@ "@legalNotices": { "description": "A link to open the legal notices on the website" }, - "privacy_policy": "Privacy policy", + "privacy_policy": "Privatumo politika", "@privacy_policy": { "description": "A link to open the privacy policy on the website" }, @@ -349,7 +349,7 @@ "@contribute_sw_development": { "description": "Button label + page title: Ways to help" }, - "contribute_develop_text": "The code for every Open Food Facts product is available on GitHub. You are welcome to reuse the code (it's open source) and help us improve it, for everyone, on all the planet.", + "contribute_develop_text": "Kiekvieno „Open Food Facts“ produkto kodą galite rasti „GitHub“. Kviečiame pakartotinai naudoti kodą (jis yra atvirojo kodo) ir padėti mums jį tobulinti visiems, visoje planetoje.", "@contribute_develop_text": {}, "contribute_develop_text_2": "You can join the Open Food Facts Slack chatroom which is the preferred way to ask questions.", "@contribute_develop_text_2": {}, @@ -429,7 +429,7 @@ "description": "Join which is actually Signup" }, "myPreferences_profile_title": "Jūsų profilis", - "myPreferences_profile_subtitle": "Manage your Open Food Facts contributor account.", + "myPreferences_profile_subtitle": "Tvarkykite savo „Open Food Facts“ paskyrą.", "myPreferences_settings_title": "Programos nustatymai", "myPreferences_settings_subtitle": "Tamsusis režimas; Analizė…", "myPreferences_food_title": "Maisto pasirinkimai", @@ -445,8 +445,8 @@ }, "ranking_tab_all": "Visi", "ranking_subtitle_match_yes": "Puikus pasirinkimas jums", - "ranking_subtitle_match_no": "Labai prastas pasirinkimas", - "ranking_subtitle_match_maybe": "Nežinomas pasirinkimas", + "ranking_subtitle_match_no": "Itin prastas atitikmuo", + "ranking_subtitle_match_maybe": "Nežinomas atitikmuo", "refresh_with_new_preferences": "Atnaujinkite sąrašą naudodami naujas nuostatas", "@refresh_with_new_preferences": { "description": "Action button label: Refresh the list with your new preferences" @@ -554,7 +554,7 @@ "@new_product_dialog_title": { "description": "Please keep it short, like 50 characters. Title of the dialog when the user searched for an unknown barcode." }, - "new_product_leave_title": "Leave this page?", + "new_product_leave_title": "Palikti šį puslapį?", "@new_product_leave_title": { "description": "Alert dialog title when a user landed on the 'add new product' page, didn't input anything and tried to leave the page." }, @@ -679,7 +679,7 @@ "@take_more_photo_button_label": {}, "other_photo_uploaded": "Įkelta įvairi nuotrauka", "@other_photo_uploaded": {}, - "retake_photo_button_label": "Retake", + "retake_photo_button_label": "Pakartoti", "@retake_photo_button_label": { "description": "Button clicking on which allows users to retake the last photo they took." }, @@ -750,7 +750,25 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, - "homepage_main_card_logo_description": "Welcome to Open Food Facts", + "product_image_accessibility_label": "Nuotrauka padaryta {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Nuotrauka padaryta {date}. Ši nuotrauka gali būti pasenusi", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "homepage_main_card_logo_description": "Sveiki atvykę į „Open Food Facts“", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" }, @@ -759,15 +777,24 @@ "description": "Text between asterisks (eg: **My Text**) means text in bold. Please keep it." }, "homepage_main_card_search_field_hint": "Ieškoti produkto", - "homepage_main_card_search_field_tooltip": "Start search", + "homepage_main_card_search_field_tooltip": "Pradėti paiešką", "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Ar jums patinka ši programėlė?", "tagline_app_review_button_positive": "Man ji labai patinka! 😍", "tagline_app_review_button_negative": "Nelabai…", "tagline_app_review_button_later": "Paklauskite manęs vėliau", - "tagline_feed_news_button": "Know more", + "tagline_feed_news_button": "Sužinoti daugiau", "app_review_negative_modal_title": "Jums nepatinka mūsų programėlė?", "app_review_negative_modal_text": "Ar galėtumėte skirti kelias sekundes ir pasakyti kodėl?", "app_review_negative_modal_positive_button": "Taip, žinoma!", @@ -776,7 +803,7 @@ "@could_not_refresh": { "description": "The product data couldn't be refreshed" }, - "product_internet_error_modal_title": "An error has occurred!", + "product_internet_error_modal_title": "Įvyko klaida!", "product_internet_error_modal_message": "We are unable to fetch information about this product due to a network error. Please check your internet connection and try again.\n\nInternal error:\n{error}", "@product_internet_error_modal_message": { "placeholders": { @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "2012 m. išradome\nbendradarbiavimo\nnuskaitymo programą", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Mums sukankant 10 metų,\nmes jį perkuriame\nnuo pat pradžių!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Tęsti", "onboarding_welcome_loading_dialog_title": "Įkeliamas jūsų pirmasis produkto pavyzdys", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibracija ir haptika", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Užpildyti pagrindinę informaciją", "not_implemented_snackbar_text": "Dar neįgyvendinta", "category_picker_page_appbar_text": "Kategorijos", - "edit_ingredients_extrait_ingredients_btn_text": "Nuskaityti ingredientus", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Atnaujinti nuotrauką", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Išgauti pakavimą", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Atnaujinti nuotrauką", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Kainos", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Pridėti kainą", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Pridėti kvitą", + "prices_add_price_tags": "Pridėti kainų etiketes", + "prices_barcode_search_not_found": "Prekė nerasta", + "prices_barcode_search_none_yet": "Dar nėra produktų", + "prices_barcode_search_question": "Ar norite ieškoti šio produkto?", + "prices_barcode_search_title": "Produktų paieška", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Kaina", "prices_amount_price_discounted": "Sumažinta kaina", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "Trūksta vieno produkto!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Valiuta", @@ -1717,7 +1814,7 @@ "prices_proof_mandatory": "You need to select a proof!", "prices_add_validation_error": "Validation error", "prices_privacy_warning_title": "Privacy warning", - "prices_privacy_warning_message": "Prices will be public, along with the store they refer to.\nThat might allow people who know about your Open Food Facts pseudonym to:\n* infer in which area you live\n* know what you are buying\nIf you are uneasy with that, please change your pseudonym, or create a new Open Food Facts account and log into the app with it.", + "prices_privacy_warning_message": "Kainos bus skelbiamos viešai, kartu pateikiant informaciją apie parduotuvę, kurioje produktas buvo pirktas.\nTai gali leisti žmonėms, žinantiems jūsų „Open Food Facts“ slapyvardį:\n* padaryti išvadą, kurioje vietovėje gyvenate\n* sužinoti, ką perkate\nJei tai jums nepatinka, galite pakeisti savo slapyvardį arba sukurti naują „Open Food Facts“ paskyrą ir su ja prisijungti prie programėlės.", "prices_unknown_product": "Nežinomas produktas", "@prices_unknown_product": { "description": "Very small text, in the context of prices, to say that the product is unknown" @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Duomenys", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Neįtraukti Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Naudoti pakartotinai ir redaguoti šią paiešką", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1758,7 +1868,7 @@ } } }, - "product_search_loading_message": "Your search of {search} is in progress.\n\nPlease wait a few seconds…", + "product_search_loading_message": "Vykdoma jūsų paieška - {search}.\n\nŠiek tiek luktelėkite…", "@product_search_loading_message": { "description": "This message will be displayed when a search is in progress.", "search": { @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Mano įrodymai", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2021,7 +2143,7 @@ "@gallery_source_label": { "description": "Label for the gallery image source" }, - "gallery_source_access_denied_dialog_title": "Access denied", + "gallery_source_access_denied_dialog_title": "Prieiga uždrausta", "@gallery_source_access_denied_dialog_title": { "description": "On iOS, the user has refused to give the permission (title of the dialog)" }, @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Įdiekite „Open Beauty Facts“, kad sukurtumėte kosmetikos duomenų bazę", "faq_title_install_pet": "Įdiekite „Open Pet Food Facts“, kad sukurtumėte naminių gyvūnų pašarų duomenų bazę", "faq_title_install_product": "Įdiekite „Open Products Facts“, kad sukurtumėte produktų duomenų bazę ir pailgintumėte objektų eksploatavimo laiką", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "„Pro“? Importuokite savo produktus į „Open Food Facts“", "contact_title_pro_email": "Gamintojo kontaktai", "contact_title_press_page": "Spaudos puslapis", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lv.arb b/packages/smooth_app/lib/l10n/app_lv.arb index 3b98d88bb2d..4ad54b5bc97 100644 --- a/packages/smooth_app/lib/l10n/app_lv.arb +++ b/packages/smooth_app/lib/l10n/app_lv.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorijas", - "edit_ingredients_extrait_ingredients_btn_text": "Ekstrakta sastāvdaļas", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Dati", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mg.arb b/packages/smooth_app/lib/l10n/app_mg.arb index bc5477540de..1b02b9c351c 100644 --- a/packages/smooth_app/lib/l10n/app_mg.arb +++ b/packages/smooth_app/lib/l10n/app_mg.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Sokajy", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Firaketana", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mi.arb b/packages/smooth_app/lib/l10n/app_mi.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_mi.arb +++ b/packages/smooth_app/lib/l10n/app_mi.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ml.arb b/packages/smooth_app/lib/l10n/app_ml.arb index 4eb28936139..32ed0e37b08 100644 --- a/packages/smooth_app/lib/l10n/app_ml.arb +++ b/packages/smooth_app/lib/l10n/app_ml.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "വിഭാഗങ്ങൾ", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mn.arb b/packages/smooth_app/lib/l10n/app_mn.arb index e1a170da020..8a115b77caa 100644 --- a/packages/smooth_app/lib/l10n/app_mn.arb +++ b/packages/smooth_app/lib/l10n/app_mn.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Ангилалууд", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mr.arb b/packages/smooth_app/lib/l10n/app_mr.arb index 58e1aeab940..271cbc1b4d9 100644 --- a/packages/smooth_app/lib/l10n/app_mr.arb +++ b/packages/smooth_app/lib/l10n/app_mr.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ms.arb b/packages/smooth_app/lib/l10n/app_ms.arb index 6a5fc38fa2c..1f0388e91eb 100644 --- a/packages/smooth_app/lib/l10n/app_ms.arb +++ b/packages/smooth_app/lib/l10n/app_ms.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Lengkapkan butiran asas", "not_implemented_snackbar_text": "Belum dilaksanakan lagi", "category_picker_page_appbar_text": "Kategori-kategori", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mt.arb b/packages/smooth_app/lib/l10n/app_mt.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_mt.arb +++ b/packages/smooth_app/lib/l10n/app_mt.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_my.arb b/packages/smooth_app/lib/l10n/app_my.arb index 36b544e1b65..3f4d81b5caf 100644 --- a/packages/smooth_app/lib/l10n/app_my.arb +++ b/packages/smooth_app/lib/l10n/app_my.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nb.arb b/packages/smooth_app/lib/l10n/app_nb.arb index 1bcaf166061..5832be15d1a 100644 --- a/packages/smooth_app/lib/l10n/app_nb.arb +++ b/packages/smooth_app/lib/l10n/app_nb.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Fullfør grunnleggende detaljer", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorier", - "edit_ingredients_extrait_ingredients_btn_text": "Hent ut ingredienser", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Oppdater bildet", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Hent ut emballasje", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Oppdater bildet", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Fant ikke produktet", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ne.arb b/packages/smooth_app/lib/l10n/app_ne.arb index 0327234d874..265c5e357ac 100644 --- a/packages/smooth_app/lib/l10n/app_ne.arb +++ b/packages/smooth_app/lib/l10n/app_ne.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nl.arb b/packages/smooth_app/lib/l10n/app_nl.arb index 4d773826f07..478c8712e5c 100644 --- a/packages/smooth_app/lib/l10n/app_nl.arb +++ b/packages/smooth_app/lib/l10n/app_nl.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Foto gemaakt op {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Afbeelding gemaakt op {date}. Deze afbeelding is mogelijk verouderd", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welkom bij Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Laatste nieuws: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Vind je de app leuk?", "tagline_app_review_button_positive": "Ik vind het geweldig! 😍", "tagline_app_review_button_negative": "Niet echt…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We hebben in 2012\nde collaboratieve\nscan-app uitgevonden", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Naar aanleiding van ons 10-jarig bestaan, vinden we onszelf opnieuw uit!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welkom !", + "onboarding_home_welcome_text2": "De app die je helpt bij het kiezen van voedsel dat goed is voor **jou** en de **planeet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Doorgaan", "onboarding_welcome_loading_dialog_title": "Uw eerste voorbeeldproduct wordt geladen", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan een streepjescode met uw camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Trillen & haptieken", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Basisdetails aanvullen", "not_implemented_snackbar_text": "Nog niet geïmplementeerd", "category_picker_page_appbar_text": "Categorieën", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingrediënten", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Detecteer de ingrediënten op de foto", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Detecteer de ingrediënten\nop de foto", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Foto laden…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Foto vernieuwen", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Verpakking uitpakken", + "edit_packaging_extract_btn_text": "Detecteer de verpakking\nop de foto", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Detecteer de verpakking op de foto", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Foto laden…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Foto vernieuwen", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Snelkoppeling naar de Prijzen-app op de productpagina", "prices_app_button": "Ga naar de Prijzen-app", "prices_generic_title": "Prijzen", + "prices_add_n_prices": "{count,plural, one {}=1{Voeg 1 prijs toe} other{Voeg {count} prijzen toe}}", + "prices_send_n_prices": "{count,plural, one {}=1{Verstuur 1 prijs} other{Verstuur {count} prijzen}}", + "prices_add_an_item": "Item toevoegen", "prices_add_a_price": "Voeg een prijs toe", - "prices_send_the_price": "Prijs verzenden", + "prices_add_a_receipt": "Een ontvangstbewijs toevoegen", + "prices_add_price_tags": "Voeg prijskaartjes toe", + "prices_barcode_search_not_found": "Geen product gevonden", + "prices_barcode_search_none_yet": "Nog geen product", + "prices_barcode_search_question": "Wilt u dit product zoeken?", + "prices_barcode_search_title": "Product zoeken", + "prices_barcode_search_running": "Zoeken naar {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Streepjescodelezer", "prices_view_prices": "Bekijk de prijzen", "prices_list_length_one_page": "{count,plural, one {}=0{Nog geen prijs} =1{Slechts één prijs} other{Alle {count} prijzen}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, one {}=0{Nog geen bewijs} =1{Slechts één bewijs} other{Alle {count} bewijzen}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Laatste {pageSize} bewijzen (totaal: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} bijdragers (totaal: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Hoeveelheid", "prices_amount_is_discounted": "Wordt er korting gegeven?", "prices_amount_price_normal": "Prijs", "prices_amount_price_discounted": "Gereduceerde prijs", "prices_amount_price_not_discounted": "Oorspronkelijke prijs", + "prices_amount_no_product": "Er ontbreekt één product!", "prices_amount_price_incorrect": "Onjuiste waarde", "prices_amount_price_mandatory": "Verplichte waarde", "prices_currency_subtitle": "Valuta", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Serverconfiguratie", + "dev_mode_section_product_page": "Productpagina", + "dev_mode_section_ui": "Gebruikersinterface", + "dev_mode_section_data": "Gegevens", + "dev_mode_section_experimental_features": "Experimentele functies", "dev_mode_hide_ecoscore_title": "Eco-Score uitsluiten", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Gebruik een spellingcontrole voor OCR-schermen", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingrediënten en verpakking)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Hergebruik en bewerk deze zoekopdracht", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Mijn bewijzen", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "Mijn bewijs", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Prijzen van bijdragers", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Laatst toegevoegde prijzen", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Installeer Open Beauty Facts om een cosmetische database te maken", "faq_title_install_pet": "Installeer Open Pet Food Facts om een dierenvoedingsdatabase te maken", "faq_title_install_product": "Installeer Open Products Facts om een productendatabase te creëren om de levensduur van objecten te verlengen", + "faq_nutriscore_nutriscore": "Nieuwe berekening van de Nutri-Score: wat is er nieuw?", "contact_title_pro_page": "Pro? Importeer je producten in Open Food Facts", "contact_title_pro_email": "Producentcontact", "contact_title_press_page": "Perspagina", @@ -2717,28 +2840,32 @@ "guide_nutriscore_v2_why_v2_title": "Waarom evolueert de Nutri-Score?", "guide_nutriscore_v2_why_v2_intro": "De Nutri-Score-formule **evolueert** om betere aanbevelingen te doen:", "guide_nutriscore_v2_why_v2_arg1_title": "Evalueert alle drankjes beter", - "guide_nutriscore_v2_why_v2_arg1_text": "The comparative notes of **milk**, **dairy drinks** with added sugar and **vegetable** drinks were better differentiated in the new algorithm.", + "guide_nutriscore_v2_why_v2_arg1_text": "De relatieve aantekeningen van **melk**, **zuiveldranken** met toegevoegde suikers en **groentedranken** werden beter gedifferentieerd in het nieuwe algoritme.", "guide_nutriscore_v2_why_v2_arg2_title": "Betere rangschikking van drankjes", - "guide_nutriscore_v2_why_v2_arg2_text": "The **sugar content** is better taken into account and favors **lowly sweetened** drinks.\\n**Sweeteners will also be penalized**: diet sodas will be downgraded from a B rating to between C and E. Water remains the recommended drink.", + "guide_nutriscore_v2_why_v2_arg2_text": "Er wordt meer rekening gehouden met het suikergehalte**, wat in voordeel is voor dranken met een laag suikergehalte.\\n** Zoetstoffen worden ook bestraft**: dieetdrankjes worden gedegradeerd van een B naar een C tot een E-score. Water is nog steeds de aanbevolen drank.", "guide_nutriscore_v2_why_v2_arg3_title": "Zout en suiker bestraft", - "guide_nutriscore_v2_why_v2_arg3_text": "Products **too sweet** or **too salty** will see their **rating further downgraded**.", + "guide_nutriscore_v2_why_v2_arg3_text": "Producten die **te zoet** of **te zout** zijn, krijgen een lagere beoordeling**.", "guide_nutriscore_v2_why_v2_arg4_title": "Hiërarchie binnen oliën en vis", "guide_nutriscore_v2_why_v2_arg4_text": "De beoordeling van bepaalde **vette vis** en **oliën rijk aan goede vetten** zal verbeteren.", "guide_nutriscore_v2_why_v2_arg5_title": "Beperk rood vlees", "guide_nutriscore_v2_why_v2_arg5_text": "De consumptie van **rood vlees moet beperkt worden**. Daarom zal **gevogelte relatief beter scoren**.", "guide_nutriscore_v2_new_logo_title": "Hoe onderscheid ik de oude Nutri-Score van de nieuwe berekening?", - "guide_nutriscore_v2_new_logo_text": "From now on, the logo can display a mention \"**New calculation**\" to clarify that this is indeed the new calculation.", + "guide_nutriscore_v2_new_logo_text": "Vanaf nu kan het logo een vermelding \"**Nieuwe berekening**\" weergeven om te verduidelijken dat het daadwerkelijk om de nieuwe berekening gaat.", "guide_nutriscore_v2_new_logo_image_caption": "Het logo van de nieuwe Nutri-Score", "guide_nutriscore_v2_where_title": "Waar vind je de nieuwe Nutri-Score berekening?", "guide_nutriscore_v2_where_paragraph1": "De Nutri-Score wordt in meerdere landen toegepast: Duitsland, België, Spanje, Frankrijk, Luxemburg, Nederland en Zwitserland.", "guide_nutriscore_v2_where_paragraph2": "Fabrikanten hebben tot uiterlijk **2026** de tijd om de oude berekening door de nieuwe te **vervangen**.", - "guide_nutriscore_v2_where_paragraph3": "Without waiting, you **will already find in the OpenFoodFacts application**, the new calculation, including if the manufacturers have not updated the score.", + "guide_nutriscore_v2_where_paragraph3": "Zonder te moeten wachten **vind je in de OpenFoodFacts applicatie** al de nieuwe berekening, ook als de fabrikanten de score nog niet hebben aangepast.", "guide_nutriscore_v2_unchanged_title": "Wat niet verandert", "guide_nutriscore_v2_unchanged_paragraph1": "De Nutri-Score is een score die is ontworpen om **de voedingskwaliteit te meten**. Het is **complementair aan de NOVA-groep** op **ultrabewerkte voedingsmiddelen** (ook aanwezig in de applicatie).", "guide_nutriscore_v2_unchanged_paragraph2": "Voor fabrikanten blijft de weergave van de Nutri-Score **optioneel**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Voorbeeld", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nn.arb b/packages/smooth_app/lib/l10n/app_nn.arb index 0547d7e7b1b..1731558508f 100644 --- a/packages/smooth_app/lib/l10n/app_nn.arb +++ b/packages/smooth_app/lib/l10n/app_nn.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorier", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_no.arb b/packages/smooth_app/lib/l10n/app_no.arb index 0547d7e7b1b..1731558508f 100644 --- a/packages/smooth_app/lib/l10n/app_no.arb +++ b/packages/smooth_app/lib/l10n/app_no.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategorier", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nr.arb b/packages/smooth_app/lib/l10n/app_nr.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_nr.arb +++ b/packages/smooth_app/lib/l10n/app_nr.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_oc.arb b/packages/smooth_app/lib/l10n/app_oc.arb index 8cff6ea17bd..efd39816bd6 100644 --- a/packages/smooth_app/lib/l10n/app_oc.arb +++ b/packages/smooth_app/lib/l10n/app_oc.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categorias", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Donadas", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_or.arb b/packages/smooth_app/lib/l10n/app_or.arb index 41ce8737e0d..b10968f9050 100644 --- a/packages/smooth_app/lib/l10n/app_or.arb +++ b/packages/smooth_app/lib/l10n/app_or.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pa.arb b/packages/smooth_app/lib/l10n/app_pa.arb index fe01acd3253..a3502859bad 100644 --- a/packages/smooth_app/lib/l10n/app_pa.arb +++ b/packages/smooth_app/lib/l10n/app_pa.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pl.arb b/packages/smooth_app/lib/l10n/app_pl.arb index 896c4759eb6..47b3825a9ed 100644 --- a/packages/smooth_app/lib/l10n/app_pl.arb +++ b/packages/smooth_app/lib/l10n/app_pl.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "W 2012 roku\nstworzyliśmy aplikację\ndo wspólnego skanowania", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Po 10. latach działania\npostanowiliśmy zaprojektować\naplikację od zera!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Kontynuuj", "onboarding_welcome_loading_dialog_title": "Ładowanie pierwszego przykładowego produktu", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Wibracje i Haptyczna Informacja Zwrotna", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Uzupełnij podstawowe informacje", "not_implemented_snackbar_text": "Jeszcze niezaimplementowane", "category_picker_page_appbar_text": "Kategorie", - "edit_ingredients_extrait_ingredients_btn_text": "Wyodrębnij składniki", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Odśwież zdjęcie", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Rozpoznaj opakowanie", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Odśwież zdjęcie", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Ceny", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Dodaj cenę", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Produkt nie został znaleziony", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Cena", "prices_amount_price_discounted": "Cena promocyjna", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Waluta", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Dane", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Wyklucz EcoScore", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Użyj ponownie i edytuj to wyszukiwanie", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Moje dowody", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pt.arb b/packages/smooth_app/lib/l10n/app_pt.arb index 9d7140c7cd0..14dccb75a57 100644 --- a/packages/smooth_app/lib/l10n/app_pt.arb +++ b/packages/smooth_app/lib/l10n/app_pt.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Gosta da aplicação?", "tagline_app_review_button_positive": "Adoro! 😍", "tagline_app_review_button_negative": "Nem por isso…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Inventamos\na aplicação de digitalização\ncolaborativa em 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Ao fazermos 10 anos,\nestamos a reinventá-la\na partir do zero!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continuar", "onboarding_welcome_loading_dialog_title": "A carregar o seu primeiro exemplo de produto", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibração e resposta tátil", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Detalhes básicos completos", "not_implemented_snackbar_text": "Ainda não implementado", "category_picker_page_appbar_text": "Categorias", - "edit_ingredients_extrait_ingredients_btn_text": "Extrair ingredientes", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Atualizar fotografia", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extrair embalagem", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Atualizar fotografia", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Atalho para a aplicação Preços na página do produto", "prices_app_button": "Ir para a aplicação Preços", "prices_generic_title": "Preços", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Adicionar um preço", - "prices_send_the_price": "Enviar o preço", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Produto não encontrado", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Pesquisa de produtos", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "Ver os preços", "prices_list_length_one_page": "{count,plural, =0{Ainda sem preço} =1{Apenas um preço} other{Todos os {count} preços}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Montante", "prices_amount_is_discounted": "Está com desconto?", "prices_amount_price_normal": "Preço", "prices_amount_price_discounted": "Preço descontado", "prices_amount_price_not_discounted": "Preço original", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Valor incorreto", "prices_amount_price_mandatory": "Valor obrigatório", "prices_currency_subtitle": "Moeda", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Dados", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Excluir Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reproduzir e editar esta pesquisa", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Minhas demonstrações", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Instale o Open Beauty Facts para criar uma base de dados de cosméticos", "faq_title_install_pet": "Instale o Open Pet Food Facts para criar uma base de dados de comida para animais de estimação", "faq_title_install_product": "Instale o Open Products Facts para criar uma base de dados de produtos para prolongar a vida útil dos objetos", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Profissional? Importe os seus produtos no Open Food Facts", "contact_title_pro_email": "Contacto do produtor", "contact_title_press_page": "Página de imprensa", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "O que não muda", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_qu.arb b/packages/smooth_app/lib/l10n/app_qu.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_qu.arb +++ b/packages/smooth_app/lib/l10n/app_qu.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_rm.arb b/packages/smooth_app/lib/l10n/app_rm.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_rm.arb +++ b/packages/smooth_app/lib/l10n/app_rm.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ro.arb b/packages/smooth_app/lib/l10n/app_ro.arb index 4ba3ec26cf3..c911d649da4 100644 --- a/packages/smooth_app/lib/l10n/app_ro.arb +++ b/packages/smooth_app/lib/l10n/app_ro.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Îți place aplicația?", "tagline_app_review_button_positive": "O ador! 😍", "tagline_app_review_button_negative": "Nu chiar...", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Am inventat\naplicația de scanare colaborativă\nîn 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Când împlinim 10 ani,\no reinventăm\nde la zero!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continuați", "onboarding_welcome_loading_dialog_title": "Se încarcă primul exemplu de produs", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibrație și haptică", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Detalii de bază complete", "not_implemented_snackbar_text": "Neimplementat încă", "category_picker_page_appbar_text": "Categorii", - "edit_ingredients_extrait_ingredients_btn_text": "Extrageți ingredientele", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Reîmprospătați fotografia", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extragere ambalaj", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Reîmprospătați fotografia", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Produsul nu a fost găsit", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Date", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Excludeți Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reutilizați și editați această căutare", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Instalați Open Beauty Facts pentru a crea o bază de date cu produse cosmetice", "faq_title_install_pet": "Instalați Open Pet Food Facts pentru a crea o bază de date cu alimente pentru animalele de companie", "faq_title_install_product": "Instalați Open Products Facts pentru a crea o bază de date de produse pentru a prelungi durata de viață a obiectelor", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Importați-vă produsele în Open Food Facts", "contact_title_pro_email": "Contact producător", "contact_title_press_page": "Apăsați Pagina", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ru.arb b/packages/smooth_app/lib/l10n/app_ru.arb index 5f6b2468344..71a326333cc 100644 --- a/packages/smooth_app/lib/l10n/app_ru.arb +++ b/packages/smooth_app/lib/l10n/app_ru.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Нравится приложение?", "tagline_app_review_button_positive": "Конечно! 😍", "tagline_app_review_button_negative": "Не очень…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "В 2012 году\nмы создали приложение\nдля коллективного сканирования", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Теперь когда нам 10 лет,\nнами было пересоздано\nполностью с нуля!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Продолжить", "onboarding_welcome_loading_dialog_title": "Загрузка вашего первого примера продукта", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Вибрация и отклик", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Детальная информация", "not_implemented_snackbar_text": "Пока что не реализовано", "category_picker_page_appbar_text": "Категории", - "edit_ingredients_extrait_ingredients_btn_text": "Распознать ингредиенты", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Обновить фото", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Извлечь информацию об упаковке", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Обновить фото", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Продукт не найден", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Данные", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Исключить Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Вы производитель? Импортируйте данные о своих продуктах в Open Food Facts", "contact_title_pro_email": "Связаться с нами (для производителей)", "contact_title_press_page": "Материалы для прессы", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sa.arb b/packages/smooth_app/lib/l10n/app_sa.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_sa.arb +++ b/packages/smooth_app/lib/l10n/app_sa.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sc.arb b/packages/smooth_app/lib/l10n/app_sc.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_sc.arb +++ b/packages/smooth_app/lib/l10n/app_sc.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sd.arb b/packages/smooth_app/lib/l10n/app_sd.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_sd.arb +++ b/packages/smooth_app/lib/l10n/app_sd.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sg.arb b/packages/smooth_app/lib/l10n/app_sg.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_sg.arb +++ b/packages/smooth_app/lib/l10n/app_sg.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_si.arb b/packages/smooth_app/lib/l10n/app_si.arb index 153b1e13d8e..e211d286d36 100644 --- a/packages/smooth_app/lib/l10n/app_si.arb +++ b/packages/smooth_app/lib/l10n/app_si.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sk.arb b/packages/smooth_app/lib/l10n/app_sk.arb index 37734ac4dc3..68e27d8b0d5 100644 --- a/packages/smooth_app/lib/l10n/app_sk.arb +++ b/packages/smooth_app/lib/l10n/app_sk.arb @@ -302,7 +302,7 @@ "@contributors_label": { "description": "Button label: Opens a pop up window where all contributors of this app are shown" }, - "contributors_dialog_title": "Contributors", + "contributors_dialog_title": "Prispievatelia", "@contributors_dialog_title": { "description": "Dialog title: A list of all contributors of this app" }, @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Páči sa vám aplikácia?", "tagline_app_review_button_positive": "Milujem to! 😍", "tagline_app_review_button_negative": "Naozaj nie…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Pokračovať", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibrácie a haptika", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Kategórie", - "edit_ingredients_extrait_ingredients_btn_text": "Rozpoznať zložky", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Odkaz na aplikáciu Ceny na stránke produktu", "prices_app_button": "Prejdite do aplikácie Ceny", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Pridajte cenu", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Výrobok sa nenašiel", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Cena", "prices_amount_price_discounted": "Zvýhodnená cena", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Mena", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Údaje", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Vylúčiť ekologické skóre", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Opätovne použite a upravte toto vyhľadávanie", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Nainštalujte si Open Beauty Facts a vytvorte kozmetickú databázu", "faq_title_install_pet": "Nainštalujte si Open Pet Food Facts a vytvorte databázu krmiva pre domáce zvieratá", "faq_title_install_product": "Nainštalujte si fakty o otvorených produktoch na vytvorenie databázy produktov na predĺženie životnosti objektov", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Importujte svoje produkty do Open Food Facts", "contact_title_pro_email": "Kontakt na výrobcu", "contact_title_press_page": "Stránka pre média", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sl.arb b/packages/smooth_app/lib/l10n/app_sl.arb index 7d95b8c9824..9ee10bb3ca8 100644 --- a/packages/smooth_app/lib/l10n/app_sl.arb +++ b/packages/smooth_app/lib/l10n/app_sl.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Kooperativno aplikacijo\nza skeniranje smo\nizumili leta 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Ker smo dopolnili 10\nbomo preoblikovali vse na novo\nod glave do pete!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Nalaganje prvega primera izdelka", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Izpolnite osnovne podatke", "not_implemented_snackbar_text": "Še ni implementirano", "category_picker_page_appbar_text": "Kategorije", - "edit_ingredients_extrait_ingredients_btn_text": "Preberi sestavine", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Osveži fotografijo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Osveži fotografijo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Podatki", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sn.arb b/packages/smooth_app/lib/l10n/app_sn.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_sn.arb +++ b/packages/smooth_app/lib/l10n/app_sn.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_so.arb b/packages/smooth_app/lib/l10n/app_so.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_so.arb +++ b/packages/smooth_app/lib/l10n/app_so.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sq.arb b/packages/smooth_app/lib/l10n/app_sq.arb index d0ff7270bb5..26aa2799529 100644 --- a/packages/smooth_app/lib/l10n/app_sq.arb +++ b/packages/smooth_app/lib/l10n/app_sq.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sr.arb b/packages/smooth_app/lib/l10n/app_sr.arb index d57da5d5803..bd2e6dd1d0f 100644 --- a/packages/smooth_app/lib/l10n/app_sr.arb +++ b/packages/smooth_app/lib/l10n/app_sr.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Категорије", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Подаци", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ss.arb b/packages/smooth_app/lib/l10n/app_ss.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_ss.arb +++ b/packages/smooth_app/lib/l10n/app_ss.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_st.arb b/packages/smooth_app/lib/l10n/app_st.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_st.arb +++ b/packages/smooth_app/lib/l10n/app_st.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sv.arb b/packages/smooth_app/lib/l10n/app_sv.arb index c094dd1a05d..6389bf35997 100644 --- a/packages/smooth_app/lib/l10n/app_sv.arb +++ b/packages/smooth_app/lib/l10n/app_sv.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Gillar du appen?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Inte riktigt…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Laddar din första exempelprodukt", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Komplettera grundläggande uppgifter", "not_implemented_snackbar_text": "Inte implementerat ännu", "category_picker_page_appbar_text": "Kategorier", - "edit_ingredients_extrait_ingredients_btn_text": "Extrahera ingredienser", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Finner ej produkt", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sw.arb b/packages/smooth_app/lib/l10n/app_sw.arb index 1e5e87b8bbb..fab8450a8da 100644 --- a/packages/smooth_app/lib/l10n/app_sw.arb +++ b/packages/smooth_app/lib/l10n/app_sw.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ta.arb b/packages/smooth_app/lib/l10n/app_ta.arb index 1410b94cfd7..a3800c17a56 100644 --- a/packages/smooth_app/lib/l10n/app_ta.arb +++ b/packages/smooth_app/lib/l10n/app_ta.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "படம் எடுக்கப்பட்ட{date} அன்று", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "{barcode} ஐத் தேடுகிறது அல்லது தேடுகிறோம்", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "சிறந்த {pageSize} பங்களிப்பாளர்கள் (மொத்தம்: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "தரவு", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "பங்களிப்பாளர் விலைகள்", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "சமீபத்திய விலைகள் சேர்க்கப்பட்டன", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/நியூட்ரிஸ்கோர்", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_te.arb b/packages/smooth_app/lib/l10n/app_te.arb index 8d0fde011e2..0c920c56da9 100644 --- a/packages/smooth_app/lib/l10n/app_te.arb +++ b/packages/smooth_app/lib/l10n/app_te.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "వర్గాలు", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tg.arb b/packages/smooth_app/lib/l10n/app_tg.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_tg.arb +++ b/packages/smooth_app/lib/l10n/app_tg.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_th.arb b/packages/smooth_app/lib/l10n/app_th.arb index 5d300909a69..6ab989ddbe1 100644 --- a/packages/smooth_app/lib/l10n/app_th.arb +++ b/packages/smooth_app/lib/l10n/app_th.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "หมวดหมู่", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "ข้อมูล", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2704,7 +2827,7 @@ "@guide_nutriscore_v2_file_language": { "description": "The logo is only available in de/en/fr/ln/nl. Please use en if not available (in lowercase, please)." }, - "guide_nutriscore_v2_what_is_nutriscore_title": "What is the Nutri-Score?", + "guide_nutriscore_v2_what_is_nutriscore_title": "อธิบายเพิ่มเติมเกี่ยวกับ Nutri-Score", "guide_nutriscore_v2_what_is_nutriscore_paragraph1": "The Nutri-Score is a logo which aims to inform you about the **nutritional quality of foods**.", "@guide_nutriscore_v2_what_is_nutriscore_paragraph1": { "description": "Text between asterisks (eg: **My Text**) means text in bold. Please try to keep it." @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ti.arb b/packages/smooth_app/lib/l10n/app_ti.arb index 255a020be81..d448c94a7d0 100644 --- a/packages/smooth_app/lib/l10n/app_ti.arb +++ b/packages/smooth_app/lib/l10n/app_ti.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tl.arb b/packages/smooth_app/lib/l10n/app_tl.arb index 87f90475326..dbcf11b0994 100644 --- a/packages/smooth_app/lib/l10n/app_tl.arb +++ b/packages/smooth_app/lib/l10n/app_tl.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Mga kategorya", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Datos", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tn.arb b/packages/smooth_app/lib/l10n/app_tn.arb index c72005b6df8..1e534e3b6c4 100644 --- a/packages/smooth_app/lib/l10n/app_tn.arb +++ b/packages/smooth_app/lib/l10n/app_tn.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tr.arb b/packages/smooth_app/lib/l10n/app_tr.arb index df64ef8876d..1ad5d380ce6 100644 --- a/packages/smooth_app/lib/l10n/app_tr.arb +++ b/packages/smooth_app/lib/l10n/app_tr.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Uygulamayı beğendiniz mi?", "tagline_app_review_button_positive": "Bayıldım! 😍", "tagline_app_review_button_negative": "Pek sayılmaz…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "İşbirliğine dayalı tarama uygulamasını 2012'de icat ettik", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "10 yaşına geldiğimizde, onu sıfırdan yeniden keşfediyoruz!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Devam et", "onboarding_welcome_loading_dialog_title": "İlk örnek ürününüz yükleniyor", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Titreşim ve Dokunma", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Temel bilgileri tamamlayın", "not_implemented_snackbar_text": "Henüz uygulanmadı", "category_picker_page_appbar_text": "Kategoriler", - "edit_ingredients_extrait_ingredients_btn_text": "İçindekileri çıkartın", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Fotoğrafı yenileyin", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Paketi ayıkla", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Fotoğrafı yenileyin", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Ürün sayfasındaki Fiyatlar uygulamasının kısayolu", "prices_app_button": "Fiyatlar uygulamasına gidin", "prices_generic_title": "Fiyatlar", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Fiyat ekleyin", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Ürün bulunamadı", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Ürün Arama", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Fiyat", "prices_amount_price_discounted": "İndirimli fiyat", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Kur", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Veri", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "EcoScore'u hariç tut", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Bu aramayı yeniden kullan ve düzenle", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Bedellerim", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Bir kozmetik veritabanı oluşturmak için Open Beauty Facts'i yükleyin", "faq_title_install_pet": "Bir evcil hayvan maması veri tabanı oluşturmak için Open Pet Food Facts'i kurun", "faq_title_install_product": "Nesnelerin ömrünü uzatmak amacıyla bir ürün veritabanı oluşturmak için Open Products Facts'i kurun", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Profesyonel mi? Open Food Facts'te ürünlerinizi içe aktarın", "contact_title_pro_email": "Üretici İletişim", "contact_title_press_page": "Basın Sayfası", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ts.arb b/packages/smooth_app/lib/l10n/app_ts.arb index c72005b6df8..1e534e3b6c4 100644 --- a/packages/smooth_app/lib/l10n/app_ts.arb +++ b/packages/smooth_app/lib/l10n/app_ts.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tt.arb b/packages/smooth_app/lib/l10n/app_tt.arb index f2239713959..84cbf7f9024 100644 --- a/packages/smooth_app/lib/l10n/app_tt.arb +++ b/packages/smooth_app/lib/l10n/app_tt.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Мәгълүмат", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tw.arb b/packages/smooth_app/lib/l10n/app_tw.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_tw.arb +++ b/packages/smooth_app/lib/l10n/app_tw.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ty.arb b/packages/smooth_app/lib/l10n/app_ty.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_ty.arb +++ b/packages/smooth_app/lib/l10n/app_ty.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ug.arb b/packages/smooth_app/lib/l10n/app_ug.arb index 62106478e8e..facddd04004 100644 --- a/packages/smooth_app/lib/l10n/app_ug.arb +++ b/packages/smooth_app/lib/l10n/app_ug.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "سانلىق مەلۇمات", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uk.arb b/packages/smooth_app/lib/l10n/app_uk.arb index 025065c82d0..bdc0ab8d9a3 100644 --- a/packages/smooth_app/lib/l10n/app_uk.arb +++ b/packages/smooth_app/lib/l10n/app_uk.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Зображення зроблене {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Зображення, зроблене {date}. Це зображення може бути застарілим", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Вітаємо в Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Останні новини: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Вам подобається цей додаток?", "tagline_app_review_button_positive": "Я в захопленні! 😍", "tagline_app_review_button_negative": "Не дуже…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Ми розробили додаток\nдля спільного сканування\nу 2012 році", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Оскільки нам виповнюється 10 років,\nми переосмислюємо його\nз нуля!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Ласкаво просимо!", + "onboarding_home_welcome_text2": "Додаток, який допоможе вам вибрати їжу, яка корисна для **вас** і **планети**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Продовжити", "onboarding_welcome_loading_dialog_title": "Завантаження вашого першого прикладу продукту", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Відскануйте штрих-код камерою", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Вібрація та тактильні відчуття", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Заповніть основні деталі", "not_implemented_snackbar_text": "Ще не реалізовано", "category_picker_page_appbar_text": "Категорії", - "edit_ingredients_extrait_ingredients_btn_text": "Вилучити інгредієнти", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Видобути інгредієнти з фото", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Отримання інгредієнтів із зображення", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Завантаження фото…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Оновити фото", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Розпакування пакунків", + "edit_packaging_extract_btn_text": "Видобути упаковку\nз фото", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Вилучення пакунка з фотографії", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Завантаження фото…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Оновити фото", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Ярлик програми «Ціни» на сторінці продукту", "prices_app_button": "Перейдіть у додаток Ціни", "prices_generic_title": "Ціни", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Додати елемент", "prices_add_a_price": "Додати ціну", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Додати чек", + "prices_add_price_tags": "Додайте цінові бірки", + "prices_barcode_search_not_found": "Товар не знайдено", + "prices_barcode_search_none_yet": "Ще немає товару", + "prices_barcode_search_question": "Ви хочете шукати цей продукт?", + "prices_barcode_search_title": "Пошук товару", + "prices_barcode_search_running": "Шукаю {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Сканер штрих-коду", "prices_view_prices": "Переглянути ціни", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Останні {pageSize} докази (всього: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Топ {pageSize} учасників (всього: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Кількість", "prices_amount_is_discounted": "Чи є знижка?", "prices_amount_price_normal": "Ціна", "prices_amount_price_discounted": "Ціна зі знижкою", "prices_amount_price_not_discounted": "Початкова ціна", + "prices_amount_no_product": "Бракує одного товару!", "prices_amount_price_incorrect": "Помилкове значення", "prices_amount_price_mandatory": "Обов'язкове значення", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Конфігурація сервера", + "dev_mode_section_product_page": "Сторінка продукту", + "dev_mode_section_ui": "Інтерфейс користувача", + "dev_mode_section_data": "Дані", + "dev_mode_section_experimental_features": "Експериментальні функції", "dev_mode_hide_ecoscore_title": "Вимкнути Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Використовуйте перевірку орфографії для OCR екранів", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Інгредієнти та упаковка)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Повторно використовуйте та редагуйте цей пошук", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "Мої докази", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "Мої докази", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Ціни вкладників", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Останні додані ціни", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Встановіть Open Beauty Facts для створення косметичної бази даних", "faq_title_install_pet": "Встановіть Open Pet Food Facts щоб створити базу даних для домашніх тварин", "faq_title_install_product": "Встановіть Open Products Facts, щоб створити базу даних продуктів і подовжити термін служби об’єктів", + "faq_nutriscore_nutriscore": "Новий розрахунок Nutri-Score: що нового?", "contact_title_pro_page": "Pro? Імпортуйте свої продукти в Open Food Facts", "contact_title_pro_email": "Контакт виробника", "contact_title_press_page": "Інформація для преси", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "Що не змінилося", "guide_nutriscore_v2_unchanged_paragraph1": "Nutri-Score – це оцінка, розроблена для **вимірювання якості харчування**. Він **доповнює групу NOVA** щодо **ультраоброблених продуктів** (також присутня в додатку).", "guide_nutriscore_v2_unchanged_paragraph2": "Для постачальників зображення Nutri-Score **залишається необов’язковим**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Попередній перегляд", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ur.arb b/packages/smooth_app/lib/l10n/app_ur.arb index bf7a84017f2..a050e760be7 100644 --- a/packages/smooth_app/lib/l10n/app_ur.arb +++ b/packages/smooth_app/lib/l10n/app_ur.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uz.arb b/packages/smooth_app/lib/l10n/app_uz.arb index aabd9f990a6..a10381b1069 100644 --- a/packages/smooth_app/lib/l10n/app_uz.arb +++ b/packages/smooth_app/lib/l10n/app_uz.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Toifalar", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Maʻlumot", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ve.arb b/packages/smooth_app/lib/l10n/app_ve.arb index c72005b6df8..1e534e3b6c4 100644 --- a/packages/smooth_app/lib/l10n/app_ve.arb +++ b/packages/smooth_app/lib/l10n/app_ve.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_vi.arb b/packages/smooth_app/lib/l10n/app_vi.arb index d14840df37a..2f38a26f8d9 100644 --- a/packages/smooth_app/lib/l10n/app_vi.arb +++ b/packages/smooth_app/lib/l10n/app_vi.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "Chúng tôi đã phát mình\nứng dụng quét cộng tác\nvào năm 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "Khi tròn 10 năm,\nchúng tôi đã phát minh lại nó\ntừ đầu!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Tiếp tục", "onboarding_welcome_loading_dialog_title": "Đang tải lên sản phẩm mẫu đầu tiên của bạn", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Rung & Phản hồi", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Hoàn thành thông tin cơ bản", "not_implemented_snackbar_text": "Chưa thực hiện", "category_picker_page_appbar_text": "Thể loại", - "edit_ingredients_extrait_ingredients_btn_text": "Trích xuất thành phần", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Làm mới ảnh", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Xuất thông tin từ bao bì", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Làm mới ảnh", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Không tìm thấy sản phẩm", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Dữ liệu", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Loại trừ Điểm sinh thái", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wa.arb b/packages/smooth_app/lib/l10n/app_wa.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_wa.arb +++ b/packages/smooth_app/lib/l10n/app_wa.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wo.arb b/packages/smooth_app/lib/l10n/app_wo.arb index c72005b6df8..1e534e3b6c4 100644 --- a/packages/smooth_app/lib/l10n/app_wo.arb +++ b/packages/smooth_app/lib/l10n/app_wo.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_xh.arb b/packages/smooth_app/lib/l10n/app_xh.arb index ed7dc42be80..cc3ec58afc4 100644 --- a/packages/smooth_app/lib/l10n/app_xh.arb +++ b/packages/smooth_app/lib/l10n/app_xh.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yi.arb b/packages/smooth_app/lib/l10n/app_yi.arb index cc484540a5f..d880cf68188 100644 --- a/packages/smooth_app/lib/l10n/app_yi.arb +++ b/packages/smooth_app/lib/l10n/app_yi.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yo.arb b/packages/smooth_app/lib/l10n/app_yo.arb index 49bea0ae59a..c1cd3ac71e0 100644 --- a/packages/smooth_app/lib/l10n/app_yo.arb +++ b/packages/smooth_app/lib/l10n/app_yo.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Awon eka", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zh.arb b/packages/smooth_app/lib/l10n/app_zh.arb index 4c2d020f672..4dd46edf3f7 100644 --- a/packages/smooth_app/lib/l10n/app_zh.arb +++ b/packages/smooth_app/lib/l10n/app_zh.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "我们在 2012 年发明了\n协作\n扫描应用程序", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "当我们 10 岁时,\n我们正在从头开始重新改变它\n!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "继续", "onboarding_welcome_loading_dialog_title": "正在加载您的第一个产品", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "振动 触觉", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "完善基本信息", "not_implemented_snackbar_text": "尚未生效", "category_picker_page_appbar_text": "類別", - "edit_ingredients_extrait_ingredients_btn_text": "提取成分", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "刷新照片", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "提取包装信息", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "刷新照片", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "數據", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "排除 Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zu.arb b/packages/smooth_app/lib/l10n/app_zu.arb index e22ad2348c2..0fc7d7f6c74 100644 --- a/packages/smooth_app/lib/l10n/app_zu.arb +++ b/packages/smooth_app/lib/l10n/app_zu.arb @@ -750,6 +750,24 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, + "product_image_accessibility_label": "Image taken on {date}", + "@product_image_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, + "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "@product_image_outdated_accessibility_label": { + "placeholders": { + "date": { + "type": "String", + "description": "The date of picture (in localized format for YYYY-MM-DD)" + } + } + }, "homepage_main_card_logo_description": "Welcome to Open Food Facts", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" @@ -763,6 +781,15 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, + "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "@scan_tagline_news_item_accessibility": { + "description": "Accessibility label for the title of a news", + "placeholders": { + "news_title": { + "type": "String" + } + } + }, "tagline_app_review": "Do you like the app?", "tagline_app_review_button_positive": "I love it! 😍", "tagline_app_review_button_negative": "Not really…", @@ -1092,14 +1119,12 @@ } } }, - "onboarding_reinventing_text1": "We invented\nthe collaborative\nscanning app in 2012", - "@onboarding_reinventing_text1": { - "description": "Onboarding / Reinventing page: text 1/2. If possible, balanced on 3 lines." - }, - "onboarding_reinventing_text2": "As we turn 10,\nwe're reinventing it\nfrom the ground up!", - "@onboarding_reinventing_text2": { - "description": "Onboarding / Reinventing page: text 2/2. If possible, balanced on 3 lines." + "onboarding_home_welcome_text1": "Welcome !", + "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "@onboarding_home_welcome_text2": { + "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, + "onboarding_continue_button": "Continue", "onboarding_welcome_loading_dialog_title": "Loading your first example product", "@onboarding_welcome_loading_dialog_title": { "description": "Title for the onboarding loading dialog" @@ -1210,6 +1235,10 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, + "camera_window_accessibility_label": "Scan a barcode with your camera", + "@camera_window_accessibility_label": { + "description": "Accessibility label for the camera window" + }, "app_haptic_feedback_title": "Vibration & Haptics", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" @@ -1450,18 +1479,34 @@ "completed_basic_details_btn_text": "Complete basic details", "not_implemented_snackbar_text": "Not implemented yet", "category_picker_page_appbar_text": "Categories", - "edit_ingredients_extrait_ingredients_btn_text": "Extract ingredients", - "@edit_ingredients_extrait_ingredients_btn_text": { + "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, + "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "@edit_ingredients_extracting_ingredients_btn_text": { + "description": "Ingredients edition - Extracting ingredients" + }, + "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "@edit_ingredients_loading_photo_btn_text": { + "description": "Ingredients edition - Loading photo from the server" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging", + "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, + "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "@edit_packaging_extracting_btn_text": { + "description": "Packaging edition - OCR-Extracting packaging" + }, + "edit_packaging_loading_photo_btn_text": "Loading photo…", + "@edit_packaging_loading_photo_btn_text": { + "description": "Packaging edition - Loading photo from the server" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1674,8 +1719,26 @@ "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", + "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", + "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", + "prices_add_an_item": "Add an item", "prices_add_a_price": "Add a price", - "prices_send_the_price": "Send the price", + "prices_add_a_receipt": "Add a receipt", + "prices_add_price_tags": "Add price tags", + "prices_barcode_search_not_found": "Product not found", + "prices_barcode_search_none_yet": "No product yet", + "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_title": "Product search", + "prices_barcode_search_running": "Looking for {barcode}", + "@prices_barcode_search_running": { + "description": "Dialog title about barcode look-up", + "placeholders": { + "barcode": { + "type": "String" + } + } + }, + "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { @@ -1698,11 +1761,45 @@ } } }, + "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "@prices_proofs_list_length_one_page": { + "description": "Number of proofs for one-page result", + "placeholders": { + "count": { + "type": "int" + } + } + }, + "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "@prices_proofs_list_length_many_pages": { + "description": "Number of proofs for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, + "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "@prices_users_list_length_many_pages": { + "description": "Number of users for one-page result", + "placeholders": { + "pageSize": { + "type": "int" + }, + "total": { + "type": "int" + } + } + }, "prices_amount_subtitle": "Amount", "prices_amount_is_discounted": "Is discounted?", "prices_amount_price_normal": "Price", "prices_amount_price_discounted": "Discounted price", "prices_amount_price_not_discounted": "Original price", + "prices_amount_no_product": "One product is missing!", "prices_amount_price_incorrect": "Incorrect value", "prices_amount_price_mandatory": "Mandatory value", "prices_currency_subtitle": "Currency", @@ -1726,10 +1823,23 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, + "dev_mode_section_server": "Server configuration", + "dev_mode_section_product_page": "Product page", + "dev_mode_section_ui": "User Interface", + "dev_mode_section_data": "Data", + "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Exclude Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, + "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "@dev_mode_spellchecker_for_ocr_title": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" + }, + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "@dev_mode_spellchecker_for_ocr_subtitle": { + "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" + }, "search_history_item_edit_tooltip": "Reuse and edit this search", "@search_history_item_edit_tooltip": { "description": "A tooltip to explain the Pen button near a search term -> it allows to reuse the item" @@ -1785,6 +1895,18 @@ "@user_search_prices_title": { "description": "User prices: list tile title" }, + "user_search_proofs_title": "My proofs", + "@user_search_proofs_title": { + "description": "User proofs: list tile title" + }, + "user_search_proof_title": "My proof", + "@user_search_proof_title": { + "description": "User proof: page title" + }, + "user_any_search_prices_title": "Contributor prices", + "@user_any_search_prices_title": { + "description": "User prices (everybody except me): list tile title" + }, "all_search_prices_latest_title": "Latest Prices added", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" @@ -2649,6 +2771,7 @@ "faq_title_install_beauty": "Install Open Beauty Facts to create a cosmetic database", "faq_title_install_pet": "Install Open Pet Food Facts to create a pet food database", "faq_title_install_product": "Install Open Products Facts to create a products database to extend the life of objects", + "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", "contact_title_pro_page": "Pro? Import your products in Open Food Facts", "contact_title_pro_email": "Producer Contact", "contact_title_press_page": "Press Page", @@ -2736,9 +2859,13 @@ "guide_nutriscore_v2_unchanged_title": "What doesn't change", "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/guide/nutriscore-v2", + "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" + }, + "preview_badge": "Preview", + "@preview_badge": { + "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" } } \ No newline at end of file From 4deb0b42a47db7dee4cb8025a20ad3e6c29fed03 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 20 Jun 2024 18:58:26 +0200 Subject: [PATCH 37/85] fix: 2 bugfixes for the tagline (empty content + image in error) (#5421) * If for some reason, there is no news, we shouldn't display the tagline at all * If the image can't be loaded, we hide it --- .../data_models/news_feed/newsfeed_model.dart | 2 + .../news_feed/newsfeed_provider.dart | 4 +- .../scan/carousel/main_card/scan_tagline.dart | 64 +++++++++++++------ 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart index 59226e46cab..c9d6cd21de0 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart @@ -9,6 +9,8 @@ class AppNews { final AppNewsList news; final AppNewsFeed feed; + bool get hasContent => news._news.isNotEmpty && feed.news.isNotEmpty; + @override String toString() { return 'AppNews{news: $news, feed: $feed}'; diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart index bbcf9acaf04..c72b44ff146 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_provider.dart @@ -40,7 +40,9 @@ class AppNewsProvider extends ChangeNotifier { AppNewsState _state; - bool get hasContent => _state is AppNewsStateLoaded; + bool get hasContent => + _state is AppNewsStateLoaded && + (_state as AppNewsStateLoaded).content.hasContent; Future loadLatestNews({bool forceUpdate = false}) async { _emit(const AppNewsStateLoading()); diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart index dc92ae9469d..1c353360d45 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart @@ -237,7 +237,7 @@ class _TagLineContentTitle extends StatelessWidget { } } -class _TagLineContentBody extends StatelessWidget { +class _TagLineContentBody extends StatefulWidget { const _TagLineContentBody({ required this.message, this.textColor, @@ -248,6 +248,13 @@ class _TagLineContentBody extends StatelessWidget { final Color? textColor; final AppNewsImage? image; + @override + State<_TagLineContentBody> createState() => _TagLineContentBodyState(); +} + +class _TagLineContentBodyState extends State<_TagLineContentBody> { + bool _imageError = false; + @override Widget build(BuildContext context) { final ThemeProvider themeProvider = context.watch(); @@ -255,35 +262,37 @@ class _TagLineContentBody extends StatelessWidget { Theme.of(context).extension()!; final Widget text = FormattedText( - text: message, + text: widget.message, textStyle: TextStyle( - color: textColor ?? + color: widget.textColor ?? (!themeProvider.isDarkMode(context) ? theme.primarySemiDark : theme.primaryLight), ), ); - if (image == null) { + if (widget.image == null) { return text; } - final int imageFlex = ((image!.width ?? 0.2) * 10).toInt(); + final int imageFlex = ((widget.image!.width ?? 0.2) * 10).toInt(); return Row( children: [ - Expanded( - flex: imageFlex, - child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: MediaQuery.sizeOf(context).height * 0.06, - ), - child: AspectRatio( - aspectRatio: 1.0, - child: _image(), + if (!_imageError) ...[ + Expanded( + flex: imageFlex, + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.sizeOf(context).height * 0.06, + ), + child: AspectRatio( + aspectRatio: 1.0, + child: _image(), + ), ), ), - ), - const SizedBox(width: MEDIUM_SPACE), + const SizedBox(width: MEDIUM_SPACE), + ], Expanded( flex: 10 - imageFlex, child: text, @@ -293,15 +302,28 @@ class _TagLineContentBody extends StatelessWidget { } Widget _image() { - if (image!.src.endsWith('svg')) { + if (widget.image!.src.endsWith('svg')) { return SvgCache( - image!.src, - semanticsLabel: image!.alt, + widget.image!.src, + semanticsLabel: widget.image!.alt, ); } else { return Image.network( - semanticLabel: image!.alt, - image!.src, + semanticLabel: widget.image!.alt, + errorBuilder: ( + BuildContext context, + Object error, + StackTrace? stackTrace, + ) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_imageError != true) { + setState(() => _imageError = true); + } + }); + + return EMPTY_WIDGET; + }, + widget.image!.src, ); } } From 5e34bbdbe2e5d329c3a98ed53840461a2d84af65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 16:35:45 +0200 Subject: [PATCH 38/85] chore(deps): bump fastlane in /packages/smooth_app/android (#5424) Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.221.0 to 2.221.1. - [Release notes](https://github.com/fastlane/fastlane/releases) - [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md) - [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.221.0...fastlane/2.221.1) --- updated-dependencies: - dependency-name: fastlane dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/android/Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/android/Gemfile.lock b/packages/smooth_app/android/Gemfile.lock index 08a141e586b..c2fcdce8648 100644 --- a/packages/smooth_app/android/Gemfile.lock +++ b/packages/smooth_app/android/Gemfile.lock @@ -16,8 +16,8 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.944.0) - aws-sdk-core (3.197.0) + aws-partitions (1.945.0) + aws-sdk-core (3.197.1) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) @@ -74,7 +74,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.221.0) + fastlane (2.221.1) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) From 5f0d3c12a135384564942f997c897477117df004 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 17:14:37 +0200 Subject: [PATCH 39/85] chore(deps): bump fastlane in /packages/smooth_app/ios (#5422) Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.221.0 to 2.221.1. - [Release notes](https://github.com/fastlane/fastlane/releases) - [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md) - [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.221.0...fastlane/2.221.1) --- updated-dependencies: - dependency-name: fastlane dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/ios/Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/ios/Gemfile.lock b/packages/smooth_app/ios/Gemfile.lock index a433dd13be8..6c82f499c3b 100644 --- a/packages/smooth_app/ios/Gemfile.lock +++ b/packages/smooth_app/ios/Gemfile.lock @@ -16,8 +16,8 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.944.0) - aws-sdk-core (3.197.0) + aws-partitions (1.945.0) + aws-sdk-core (3.197.1) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) @@ -75,7 +75,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.221.0) + fastlane (2.221.1) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) From ad9c06eaf8d69989afde97181ef5ac1c885161f5 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 21 Jun 2024 17:15:09 +0200 Subject: [PATCH 40/85] feat: OCR: Better explain why the photo is still loading (#5426) * OCR: Better explain why the photo is loading * Add missing file --- .../dialogs/smooth_alert_dialog.dart | 49 ++++++++-- packages/smooth_app/lib/l10n/app_en.arb | 16 ++++ .../edit_ocr/edit_ocr_main_action.dart | 93 ++++++++++++++++++- .../pages/product/edit_ocr/edit_ocr_page.dart | 1 + .../pages/product/edit_ocr/ocr_helper.dart | 8 ++ .../edit_ocr/ocr_ingredients_helper.dart | 8 ++ .../edit_ocr/ocr_packaging_helper.dart | 8 ++ 7 files changed, 169 insertions(+), 14 deletions(-) diff --git a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart index 5e3476ba7da..f267cc1dba6 100644 --- a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart +++ b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart @@ -26,6 +26,7 @@ import 'package:smooth_app/helpers/keyboard_helper.dart'; class SmoothAlertDialog extends StatelessWidget { const SmoothAlertDialog({ this.title, + this.leadingTitle, required this.body, this.positiveAction, this.negativeAction, @@ -41,6 +42,7 @@ class SmoothAlertDialog extends StatelessWidget { ); final String? title; + final Widget? leadingTitle; final bool close; final Widget body; final SmoothActionButton? positiveAction; @@ -143,7 +145,12 @@ class SmoothAlertDialog extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - if (title != null) _SmoothDialogTitle(label: title!, close: close), + if (title != null) + _SmoothDialogTitle( + label: title!, + close: close, + leading: leadingTitle, + ), body, ], ), @@ -158,15 +165,20 @@ class _SmoothDialogTitle extends StatelessWidget { const _SmoothDialogTitle({ required this.label, required this.close, + this.leading, }); static const double _titleHeight = 32.0; final String label; final bool close; + final Widget? leading; @override Widget build(BuildContext context) { + final TextStyle textStyle = + Theme.of(context).textTheme.displayMedium ?? const TextStyle(); + return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -176,12 +188,24 @@ class _SmoothDialogTitle extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ + if (leading != null) + Padding( + padding: EdgeInsetsDirectional.only( + top: leading is Icon ? 2.0 : 0.0, + end: SMALL_SPACE, + ), + child: IconTheme( + data: IconThemeData( + color: textStyle.color, + ), + child: leading!), + ), _buildCross(true), Expanded( child: FittedBox( child: Text( label, - style: Theme.of(context).textTheme.displayMedium, + style: textStyle, ), ), ), @@ -221,16 +245,21 @@ class _SmoothDialogCrossButton extends StatelessWidget { maintainAnimation: true, maintainState: true, visible: visible, - child: InkWell( - customBorder: const CircleBorder(), - child: const Padding( - padding: EdgeInsets.all(SMALL_SPACE), - child: Icon( - Icons.close, - size: _SmoothDialogTitle._titleHeight - (2 * SMALL_SPACE), + child: Semantics( + label: MaterialLocalizations.of(context).closeButtonLabel, + button: true, + excludeSemantics: true, + child: InkWell( + customBorder: const CircleBorder(), + child: const Padding( + padding: EdgeInsets.all(SMALL_SPACE), + child: Icon( + Icons.close, + size: _SmoothDialogTitle._titleHeight - (2 * SMALL_SPACE), + ), ), + onTap: () => Navigator.of(context, rootNavigator: true).pop(), ), - onTap: () => Navigator.of(context, rootNavigator: true).pop(), ), ); } else { diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index b083ea0a688..576149baf18 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart index 3cf5930fce8..6fa71cb85e7 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart @@ -113,14 +113,13 @@ class _EditOcrActionExtractingContent extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - const CircularProgressIndicator.adaptive(), + const _ExtractMainActionProgressIndicator(), Expanded( child: Text( helper.getActionExtractingData(appLocalizations), textAlign: TextAlign.center, ), ), - const CircularProgressIndicator.adaptive(), ], ), ), @@ -184,21 +183,107 @@ class _EditOcrActionLoadingContent extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE), + padding: const EdgeInsetsDirectional.only( + start: MEDIUM_SPACE, + end: VERY_SMALL_SPACE, + ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + const _ExtractMainActionProgressIndicator(), Expanded( child: Text( helper.getActionLoadingPhoto(appLocalizations), ), ), - const CircularProgressIndicator.adaptive(), + AspectRatio( + aspectRatio: 1.0, + child: InkWell( + onTap: () => _openExplanation(context), + borderRadius: ANGULAR_BORDER_RADIUS, + child: Icon( + Icons.info_outline, + semanticLabel: helper.getActionLoadingPhotoDialogTitle( + appLocalizations, + ), + ), + ), + ) ], ), ); } + + void _openExplanation(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + + return SmoothAlertDialog( + title: helper.getActionLoadingPhotoDialogTitle( + appLocalizations, + ), + leadingTitle: const Icon( + Icons.info_outline, + semanticLabel: '', + ), + close: true, + body: Text( + helper.getActionLoadingPhotoDialogBody( + appLocalizations, + ), + ), + positiveAction: SmoothActionButton( + text: appLocalizations.okay, + onPressed: () => Navigator.pop(context), + ), + ); + }, + ); + } +} + +/// We use a custom progress indicator, because Material and Cupertino Widgets +/// don't have the same size. +class _ExtractMainActionProgressIndicator extends StatelessWidget { + const _ExtractMainActionProgressIndicator(); + + @override + Widget build(BuildContext context) { + if (Platform.isIOS || Platform.isMacOS) { + return const Padding( + padding: EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: MEDIUM_SPACE, + top: SMALL_SPACE, + bottom: SMALL_SPACE, + ), + child: CupertinoActivityIndicator( + radius: 10.0, + color: Colors.white, + ), + ); + } + + return const Padding( + padding: EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: MEDIUM_SPACE, + top: MEDIUM_SPACE, + bottom: MEDIUM_SPACE, + ), + child: AspectRatio( + aspectRatio: 1.0, + child: CircularProgressIndicator( + strokeWidth: 2.5, + valueColor: AlwaysStoppedAnimation(Colors.white), + // backgroundColor: Colors.white, + ), + ), + ); + } } enum _OcrState { diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index 88479a33be6..1f737bc5744 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/ocr_helper.dart b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_helper.dart index 2a232e05e04..f8cdc759b71 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/ocr_helper.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_helper.dart @@ -42,6 +42,14 @@ abstract class OcrHelper { /// Returns the "loading photo" button label String getActionLoadingPhoto(final AppLocalizations appLocalizations); + /// Returns the title of the dialog to explain the "loading photo" state + String getActionLoadingPhotoDialogTitle( + final AppLocalizations appLocalizations); + + /// Returns the content of the dialog to explain the "loading photo" state + String getActionLoadingPhotoDialogBody( + final AppLocalizations appLocalizations); + /// Returns the "Extracting data…" button label String getActionExtractingData(final AppLocalizations appLocalizations); diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart index a721059e75a..d2720d98b57 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_ingredients_helper.dart @@ -53,6 +53,14 @@ class OcrIngredientsHelper extends OcrHelper { String getActionLoadingPhoto(AppLocalizations appLocalizations) => appLocalizations.edit_ingredients_loading_photo_btn_text; + @override + String getActionLoadingPhotoDialogTitle(AppLocalizations appLocalizations) => + appLocalizations.edit_ingredients_loading_photo_help_dialog_title; + + @override + String getActionLoadingPhotoDialogBody(AppLocalizations appLocalizations) => + appLocalizations.edit_ingredients_loading_photo_help_dialog_body; + @override String getActionRefreshPhoto(final AppLocalizations appLocalizations) => appLocalizations.edit_ingredients_refresh_photo_btn_text; diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart index a22d6f94350..6590f15a993 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/ocr_packaging_helper.dart @@ -56,6 +56,14 @@ class OcrPackagingHelper extends OcrHelper { String getActionLoadingPhoto(AppLocalizations appLocalizations) => appLocalizations.edit_packaging_loading_photo_btn_text; + @override + String getActionLoadingPhotoDialogTitle(AppLocalizations appLocalizations) => + appLocalizations.edit_packaging_loading_photo_help_dialog_title; + + @override + String getActionLoadingPhotoDialogBody(AppLocalizations appLocalizations) => + appLocalizations.edit_packaging_loading_photo_help_dialog_body; + @override String getActionRefreshPhoto(final AppLocalizations appLocalizations) => appLocalizations.edit_packaging_refresh_photo_btn_text; From 60a898f51e88453a6394874e29a6d539b5279bcd Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 21 Jun 2024 17:15:36 +0200 Subject: [PATCH 41/85] chore: Remove Scan Example page from the onboarding (#5420) * Remove Scan Example page from the onboarding * Remove unused translation --- .../smooth_app/assets/onboarding/scan.svg | 74 ------------------- .../lib/data_models/onboarding_loader.dart | 1 - packages/smooth_app/lib/l10n/app_en.arb | 4 - .../onboarding/onboarding_flow_navigator.dart | 9 --- .../lib/pages/onboarding/scan_example.dart | 73 ------------------ 5 files changed, 161 deletions(-) delete mode 100644 packages/smooth_app/assets/onboarding/scan.svg delete mode 100644 packages/smooth_app/lib/pages/onboarding/scan_example.dart diff --git a/packages/smooth_app/assets/onboarding/scan.svg b/packages/smooth_app/assets/onboarding/scan.svg deleted file mode 100644 index 0baf01438d4..00000000000 --- a/packages/smooth_app/assets/onboarding/scan.svg +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/smooth_app/lib/data_models/onboarding_loader.dart b/packages/smooth_app/lib/data_models/onboarding_loader.dart index 2b8602e0850..33a193971f3 100644 --- a/packages/smooth_app/lib/data_models/onboarding_loader.dart +++ b/packages/smooth_app/lib/data_models/onboarding_loader.dart @@ -45,7 +45,6 @@ class OnboardingLoader { return; case OnboardingPage.NOT_STARTED: case OnboardingPage.HOME_PAGE: - case OnboardingPage.SCAN_EXAMPLE: case OnboardingPage.HEALTH_CARD_EXAMPLE: case OnboardingPage.ECO_CARD_EXAMPLE: case OnboardingPage.PREFERENCES_PAGE: diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 576149baf18..61d06ebe8e5 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -129,10 +129,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart index bdc88299518..2391b6abb1d 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_flow_navigator.dart @@ -9,7 +9,6 @@ import 'package:smooth_app/pages/onboarding/preferences_page.dart'; import 'package:smooth_app/pages/onboarding/reinvention_page.dart'; import 'package:smooth_app/pages/onboarding/sample_eco_card_page.dart'; import 'package:smooth_app/pages/onboarding/sample_health_card_page.dart'; -import 'package:smooth_app/pages/onboarding/scan_example.dart'; import 'package:smooth_app/pages/onboarding/welcome_page.dart'; import 'package:smooth_app/pages/page_manager.dart'; import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; @@ -20,7 +19,6 @@ enum OnboardingPage { NOT_STARTED, HOME_PAGE, WELCOME, - SCAN_EXAMPLE, HEALTH_CARD_EXAMPLE, ECO_CARD_EXAMPLE, PREFERENCES_PAGE, @@ -56,8 +54,6 @@ enum OnboardingPage { return const Color(0xFFDFF4FF); case OnboardingPage.WELCOME: return const Color(0xFFFCFCFC); - case OnboardingPage.SCAN_EXAMPLE: - return const Color(0xFFE3F6FF); case OnboardingPage.HEALTH_CARD_EXAMPLE: return const Color(0xFFFFF1D1); case OnboardingPage.ECO_CARD_EXAMPLE: @@ -83,11 +79,6 @@ enum OnboardingPage { return const OnboardingHomePage(); case OnboardingPage.WELCOME: return WelcomePage(backgroundColor); - case OnboardingPage.SCAN_EXAMPLE: - return _wrapWidgetInCustomBackNavigator( - context, - ScanExample(backgroundColor), - ); case OnboardingPage.HEALTH_CARD_EXAMPLE: return _wrapWidgetInCustomBackNavigator( context, diff --git a/packages/smooth_app/lib/pages/onboarding/scan_example.dart b/packages/smooth_app/lib/pages/onboarding/scan_example.dart deleted file mode 100644 index 52646e02f03..00000000000 --- a/packages/smooth_app/lib/pages/onboarding/scan_example.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'dart:io'; - -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/helpers/app_helper.dart'; -import 'package:smooth_app/pages/onboarding/next_button.dart'; -import 'package:smooth_app/pages/onboarding/onboarding_flow_navigator.dart'; -import 'package:smooth_app/widgets/smooth_text.dart'; - -/// Example explanation on how to scan a product. -class ScanExample extends StatelessWidget { - const ScanExample(this.backgroundColor); - - final Color backgroundColor; - - @override - Widget build(BuildContext context) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - final Size screenSize = MediaQuery.sizeOf(context); - return ColoredBox( - color: backgroundColor, - child: SafeArea( - bottom: Platform.isAndroid, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Used for spacing - EMPTY_WIDGET, - Padding( - padding: const EdgeInsets.symmetric(horizontal: LARGE_SPACE), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SvgPicture.asset( - 'assets/onboarding/scan.svg', - height: screenSize.height * .50, - package: AppHelper.APP_PACKAGE, - ), - Padding( - padding: const EdgeInsetsDirectional.only(top: SMALL_SPACE), - child: SizedBox( - height: screenSize.height * .15, - child: AutoSizeText( - appLocalizations.offUtility, - maxLines: 2, - style: Theme.of(context) - .textTheme - .displayLarge! - .wellSpaced - .apply( - color: const Color.fromARGB(255, 51, 51, 51)), - ), - ), - ), - ], - ), - ), - NextButton( - OnboardingPage.SCAN_EXAMPLE, - backgroundColor: backgroundColor, - nextKey: const Key('nextAfterScanExample'), - ), - ], - ), - ), - ); - } -} From eb03ed1ecfbe010b6e191ce665ee7a148409a7cc Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 22 Jun 2024 08:48:23 +0200 Subject: [PATCH 42/85] Fix Linux / Windows error (#5431) --- .../smooth_app/lib/database/local_database.dart | 12 ++++++++---- packages/smooth_app/pubspec.lock | 16 ++++++++++++++++ packages/smooth_app/pubspec.yaml | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/smooth_app/lib/database/local_database.dart b/packages/smooth_app/lib/database/local_database.dart index 364238f991b..b3542785dee 100644 --- a/packages/smooth_app/lib/database/local_database.dart +++ b/packages/smooth_app/lib/database/local_database.dart @@ -21,7 +21,7 @@ import 'package:smooth_app/database/dao_string_list.dart'; import 'package:smooth_app/database/dao_string_list_map.dart'; import 'package:smooth_app/database/dao_transient_operation.dart'; import 'package:smooth_app/database/dao_work_barcode.dart'; -import 'package:sqflite/sqflite.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; class LocalDatabase extends ChangeNotifier { LocalDatabase._(final Database database) : _database = database { @@ -53,14 +53,18 @@ class LocalDatabase extends ChangeNotifier { static Future getLocalDatabase() async { // sql from there - final String databasesRootPath; + String? databasesRootPath; if (defaultTargetPlatform == TargetPlatform.iOS) { // as suggested in https://pub.dev/documentation/sqflite/latest/sqflite/getDatabasesPath.html final Directory directory = await getLibraryDirectory(); databasesRootPath = directory.path; - } else { - databasesRootPath = await getDatabasesPath(); + } else if (Platform.isLinux || Platform.isWindows) { + sqfliteFfiInit(); + databaseFactory = databaseFactoryFfi; } + + databasesRootPath ??= await getDatabasesPath(); + final String databasePath = join(databasesRootPath, 'smoothie.db'); final Database database = await openDatabase( databasePath, diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index f4fb9affda7..eaec5236455 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -1523,6 +1523,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.4" + sqflite_common_ffi: + dependency: "direct main" + description: + name: sqflite_common_ffi + sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202" + url: "https://pub.dev" + source: hosted + version: "2.4.2" stack_trace: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 0b428986d43..c0f7b8ff438 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: provider: 6.1.2 sentry_flutter: 7.18.0 sqflite: 2.3.3+1 + sqflite_common_ffi: 2.3.3 url_launcher: 6.1.3 visibility_detector: 0.4.0+2 assorted_layout_widgets: 9.0.1 From ba8313c0b2fe1a56f61857342cf7270c2e868770 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 22 Jun 2024 09:40:37 +0200 Subject: [PATCH 43/85] Depending of the state of preferences, the onboarding exit may fail (#5433) --- .../preferences/migration/user_preferences_migration.dart | 2 +- .../lib/data_models/preferences/user_preferences.dart | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/smooth_app/lib/data_models/preferences/migration/user_preferences_migration.dart b/packages/smooth_app/lib/data_models/preferences/migration/user_preferences_migration.dart index 08a8b8b1406..5cdb4b9766d 100644 --- a/packages/smooth_app/lib/data_models/preferences/migration/user_preferences_migration.dart +++ b/packages/smooth_app/lib/data_models/preferences/migration/user_preferences_migration.dart @@ -78,7 +78,7 @@ class _UserPreferencesMigrationV2 extends UserPreferencesMigration { null) { await preferences._sharedPreferences.setInt( UserPreferences._TAG_USER_GROUP, - Random().nextInt(10), + math.Random().nextInt(10), ); } } diff --git a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart index 6bed2453a2d..e80cbd9be8b 100644 --- a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart +++ b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart @@ -1,4 +1,4 @@ -import 'dart:math'; +import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; @@ -189,7 +189,7 @@ class UserPreferences extends ChangeNotifier { if (result != null) { return result; } - result = Random().nextInt(1 << 32); + result = math.Random().nextInt(1 << 32); await _sharedPreferences.setInt(tag, result); return result; } @@ -251,7 +251,8 @@ class UserPreferences extends ChangeNotifier { _sharedPreferences.getInt(_TAG_LAST_VISITED_ONBOARDING_PAGE); return pageIndex == null ? OnboardingPage.NOT_STARTED - : OnboardingPage.values[pageIndex]; + : OnboardingPage + .values[math.min(pageIndex, OnboardingPage.values.length - 1)]; } Future incrementScanCount() async { From 4499eefdad3c30b355000ca1cb98edcbdcc2d26b Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 24 Jun 2024 07:10:36 +0200 Subject: [PATCH 44/85] Upload indicator for the image viewer (#5425) --- .../product/product_image_gallery_view.dart | 18 +--- .../pages/product/product_image_viewer.dart | 92 ++++++++++++------- .../lib/resources/app_animations.dart | 46 +++++++++- 3 files changed, 100 insertions(+), 56 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart index 4c4a217c088..26197d46234 100644 --- a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart +++ b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart @@ -219,23 +219,7 @@ class _PhotoRow extends StatelessWidget { textDirection: Directionality.of(context), bottom: VERY_SMALL_SPACE, end: VERY_SMALL_SPACE, - width: 30.0, - height: 30.0, - child: DecoratedBox( - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.5), - shape: BoxShape.circle, - ), - child: const Padding( - padding: EdgeInsetsDirectional.only( - start: SMALL_SPACE, - end: SMALL_SPACE, - top: SMALL_SPACE, - bottom: SMALL_SPACE - 1.0, - ), - child: CloudUploadAnimation(), - ), - ), + child: const CloudUploadAnimation.circle(size: 30.0), ), ], ), diff --git a/packages/smooth_app/lib/pages/product/product_image_viewer.dart b/packages/smooth_app/lib/pages/product/product_image_viewer.dart index 1f43d5cfd76..f92e8ece55c 100644 --- a/packages/smooth_app/lib/pages/product/product_image_viewer.dart +++ b/packages/smooth_app/lib/pages/product/product_image_viewer.dart @@ -8,11 +8,13 @@ import 'package:smooth_app/data_models/up_to_date_mixin.dart'; import 'package:smooth_app/database/local_database.dart'; import 'package:smooth_app/database/transient_file.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/duration_constants.dart'; import 'package:smooth_app/generic_lib/widgets/language_selector.dart'; import 'package:smooth_app/generic_lib/widgets/picture_not_found.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/image_crop_page.dart'; import 'package:smooth_app/pages/product/product_image_button.dart'; +import 'package:smooth_app/resources/app_animations.dart'; /// Displays a full-screen image with an "edit" floating button. class ProductImageViewer extends StatefulWidget { @@ -69,8 +71,11 @@ class _ProductImageViewerState extends State widget.imageField, widget.language, ); - final ImageProvider? imageProvider = _getTransientFile().getImageProvider(); + final TransientFile transientFile = _getTransientFile(); + final ImageProvider? imageProvider = transientFile.getImageProvider(); final bool imageExists = imageProvider != null; + final bool isLoading = + transientFile.isImageAvailable() && !transientFile.isServerImage(); final Iterable selectedLanguages = getProductImageLanguages( upToDateProduct, @@ -124,40 +129,59 @@ class _ProductImageViewerState extends State ), ], ) - : PhotoView( - minScale: 0.2, - imageProvider: imageProvider, - heroAttributes: PhotoViewHeroAttributes( - tag: 'photo_${widget.imageField.offTag}', - flightShuttleBuilder: ( - _, - Animation animation, - HeroFlightDirection flightDirection, - BuildContext fromHeroContext, - BuildContext toHeroContext, - ) { - return AnimatedBuilder( - animation: animation, - builder: (_, __) { - Widget widget; - if (flightDirection == - HeroFlightDirection.push) { - widget = fromHeroContext.widget; - } else { - widget = toHeroContext.widget; - } + : SizedBox.expand( + child: Stack( + children: [ + Positioned.fill( + child: AnimatedOpacity( + opacity: isLoading ? 0.5 : 1.0, + duration: SmoothAnimationsDuration.short, + child: PhotoView( + minScale: 0.2, + imageProvider: imageProvider, + heroAttributes: PhotoViewHeroAttributes( + tag: 'photo_${widget.imageField.offTag}', + flightShuttleBuilder: ( + _, + Animation animation, + HeroFlightDirection flightDirection, + BuildContext fromHeroContext, + BuildContext toHeroContext, + ) { + return AnimatedBuilder( + animation: animation, + builder: (_, __) { + Widget widget; + if (flightDirection == + HeroFlightDirection.push) { + widget = fromHeroContext.widget; + } else { + widget = toHeroContext.widget; + } - return ClipRRect( - borderRadius: BorderRadius.circular( - 1 - animation.value) * - ROUNDED_RADIUS.x, - child: widget, - ); - }, - ); - }), - backgroundDecoration: const BoxDecoration( - color: Colors.black, + return ClipRRect( + borderRadius: BorderRadius.circular( + 1 - animation.value) * + ROUNDED_RADIUS.x, + child: widget, + ); + }, + ); + }), + backgroundDecoration: const BoxDecoration( + color: Colors.black, + ), + ), + ), + ), + if (isLoading) + Center( + child: CloudUploadAnimation.circle( + size: MediaQuery.sizeOf(context).longestSide * + 0.2, + ), + ), + ], ), ), ), diff --git a/packages/smooth_app/lib/resources/app_animations.dart b/packages/smooth_app/lib/resources/app_animations.dart index d128b99a2e2..3086c71208b 100644 --- a/packages/smooth_app/lib/resources/app_animations.dart +++ b/packages/smooth_app/lib/resources/app_animations.dart @@ -75,15 +75,51 @@ class BarcodeAnimation extends StatelessWidget { class CloudUploadAnimation extends StatelessWidget { const CloudUploadAnimation({ + required this.size, super.key, - }); + }) : _circleColor = null; + + const CloudUploadAnimation.circle({ + required this.size, + Color? circleColor, + super.key, + }) : _circleColor = circleColor ?? Colors.black54; + + final double size; + final Color? _circleColor; @override Widget build(BuildContext context) { - return RiveAnimation.direct( - AnimationsLoader.of(context), - artboard: 'Cloud upload', - animations: const ['Animation'], + Widget widget = SizedBox.square( + dimension: size, + child: RiveAnimation.direct( + AnimationsLoader.of(context), + artboard: 'Cloud upload', + animations: const ['Animation'], + ), + ); + + if (_circleColor != null) { + widget = DecoratedBox( + decoration: BoxDecoration( + color: _circleColor, + shape: BoxShape.circle, + ), + child: Padding( + padding: EdgeInsetsDirectional.only( + top: size * 0.2, + start: size * 0.2, + end: size * 0.2, + bottom: size * 0.13, + ), + child: widget, + ), + ); + } + + return SizedBox.square( + dimension: size, + child: widget, ); } } From 333b5acde6ddfc9aadd1badd6b30e2f96f2486b3 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 24 Jun 2024 19:20:23 +0200 Subject: [PATCH 45/85] chore: Tagline: minor UI changes (paddings) (#5440) * Some UI changes (paddings) + matomo event * Actually, tracking the link with Matomo is not needed --- .../lib/pages/scan/carousel/main_card/scan_main_card.dart | 7 +++++-- .../lib/pages/scan/carousel/main_card/scan_tagline.dart | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart index 31010c12ae9..26e15c4bf4d 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart @@ -42,7 +42,7 @@ class ScanMainCard extends StatelessWidget { expandedMode: false, ), ), - SizedBox(height: MEDIUM_SPACE), + SizedBox(height: SMALL_SPACE), Expanded( flex: 4, child: ScanTagLine(), @@ -97,7 +97,10 @@ class _SearchCard extends StatelessWidget { textAlign: TextAlign.center, textStyle: const TextStyle(height: 1.3), ), - const _SearchBar(), + const Padding( + padding: EdgeInsets.symmetric(horizontal: SMALL_SPACE), + child: _SearchBar(), + ), ], ), ); diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart index 1c353360d45..6fce8fabb61 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart @@ -220,7 +220,7 @@ class _TagLineContentTitle extends StatelessWidget { ), ), ), - const SizedBox(width: SMALL_SPACE), + const SizedBox(width: VERY_SMALL_SPACE), Expanded( child: Text( title, From 8d16324f11711cc58439c95da6a659173a31f83f Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 24 Jun 2024 19:20:38 +0200 Subject: [PATCH 46/85] Add `TraceableClientMixin` to prices pages (#5441) --- .../lib/pages/prices/price_product_search_page.dart | 5 ++++- .../smooth_app/lib/pages/prices/prices_proofs_page.dart | 4 +++- .../smooth_app/lib/pages/prices/prices_users_page.dart | 4 +++- .../lib/pages/prices/product_price_add_page.dart | 8 +++++++- .../smooth_app/lib/pages/prices/product_prices_list.dart | 4 +++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart index e16b639b764..fcfc88b81fb 100644 --- a/packages/smooth_app/lib/pages/prices/price_product_search_page.dart +++ b/packages/smooth_app/lib/pages/prices/price_product_search_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:matomo_tracker/matomo_tracker.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/fetched_product.dart'; @@ -26,13 +27,15 @@ class PriceProductSearchPage extends StatefulWidget { }); final PriceMetaProduct? product; + // TODO(monsieurtanuki): as a parameter, add a list of barcodes already there: we're not supposed to select twice the same product @override State createState() => _PriceProductSearchPageState(); } -class _PriceProductSearchPageState extends State { +class _PriceProductSearchPageState extends State + with TraceableClientMixin { final TextEditingController _controller = TextEditingController(); late PriceMetaProduct? _product = widget.product; diff --git a/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart b/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart index fe5f202231c..fac691981f4 100644 --- a/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart +++ b/packages/smooth_app/lib/pages/prices/prices_proofs_page.dart @@ -2,6 +2,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; +import 'package:matomo_tracker/matomo_tracker.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; @@ -21,7 +22,8 @@ class PricesProofsPage extends StatefulWidget { State createState() => _PricesProofsPageState(); } -class _PricesProofsPageState extends State { +class _PricesProofsPageState extends State + with TraceableClientMixin { late final Future> _results = _download(); static const int _columns = 3; diff --git a/packages/smooth_app/lib/pages/prices/prices_users_page.dart b/packages/smooth_app/lib/pages/prices/prices_users_page.dart index 07a32bbe50f..4ec9283aaec 100644 --- a/packages/smooth_app/lib/pages/prices/prices_users_page.dart +++ b/packages/smooth_app/lib/pages/prices/prices_users_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:matomo_tracker/matomo_tracker.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; @@ -20,7 +21,8 @@ class PricesUsersPage extends StatefulWidget { State createState() => _PricesUsersPageState(); } -class _PricesUsersPageState extends State { +class _PricesUsersPageState extends State + with TraceableClientMixin { late final Future> _users = _showTopUsers(); // In this specific page, let's never try to go beyond the top 10. diff --git a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart index d851750fc1f..733098d9703 100644 --- a/packages/smooth_app/lib/pages/prices/product_price_add_page.dart +++ b/packages/smooth_app/lib/pages/prices/product_price_add_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:matomo_tracker/matomo_tracker.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; @@ -56,6 +57,7 @@ class ProductPriceAddPage extends StatefulWidget { if (!context.mounted) { return; } + await Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => ProductPriceAddPage( @@ -71,7 +73,8 @@ class ProductPriceAddPage extends StatefulWidget { State createState() => _ProductPriceAddPageState(); } -class _ProductPriceAddPageState extends State { +class _ProductPriceAddPageState extends State + with TraceableClientMixin { late final PriceModel _model = PriceModel( proofType: widget.proofType, locations: widget.latestOsmLocations, @@ -244,4 +247,7 @@ class _ProductPriceAddPageState extends State { } return true; } + + @override + String get actionName => 'Opened price_page with ${widget.proofType.offTag}'; } diff --git a/packages/smooth_app/lib/pages/prices/product_prices_list.dart b/packages/smooth_app/lib/pages/prices/product_prices_list.dart index 61b82d54203..8f30271732d 100644 --- a/packages/smooth_app/lib/pages/prices/product_prices_list.dart +++ b/packages/smooth_app/lib/pages/prices/product_prices_list.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:matomo_tracker/matomo_tracker.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; @@ -20,7 +21,8 @@ class ProductPricesList extends StatefulWidget { State createState() => _ProductPricesListState(); } -class _ProductPricesListState extends State { +class _ProductPricesListState extends State + with TraceableClientMixin { late final Future> _prices = _showProductPrices(widget.model.parameters); From b110334c3d577683969270baddae6e6d9ad9046b Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 25 Jun 2024 08:22:11 +0200 Subject: [PATCH 47/85] feat: A feedback form for the prices page (#5442) * A feedback form for the prices page * Fix --- .../preferences/user_preferences.dart | 9 ++ packages/smooth_app/lib/l10n/app_en.arb | 4 + .../lib/pages/prices/prices_card.dart | 10 +- .../lib/pages/prices/prices_page.dart | 99 +++++++++++++++++++ 4 files changed, 117 insertions(+), 5 deletions(-) diff --git a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart index e80cbd9be8b..012fa624aec 100644 --- a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart +++ b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart @@ -75,6 +75,7 @@ class UserPreferences extends ChangeNotifier { static const String _TAG_DEV_MODE = 'devMode'; static const String _TAG_USER_TRACKING = 'user_tracking'; static const String _TAG_CRASH_REPORTS = 'crash_reports'; + static const String _TAG_PRICES_FEEDBACK_FORM = 'prices_feedback_form'; static const String _TAG_EXCLUDED_ATTRIBUTE_IDS = 'excluded_attributes'; static const String _TAG_USER_GROUP = '_user_group'; static const String _TAG_UNIQUE_RANDOM = '_unique_random'; @@ -203,6 +204,14 @@ class UserPreferences extends ChangeNotifier { bool get crashReports => _sharedPreferences.getBool(_TAG_CRASH_REPORTS) ?? false; + Future markPricesFeedbackFormAsCompleted() async { + await _sharedPreferences.setBool(_TAG_PRICES_FEEDBACK_FORM, false); + notifyListeners(); + } + + bool get shouldShowPricesFeedbackForm => + _sharedPreferences.getBool(_TAG_PRICES_FEEDBACK_FORM) ?? true; + String get currentTheme => _sharedPreferences.getString(_TAG_CURRENT_THEME_MODE) ?? THEME_SYSTEM_DEFAULT; diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 61d06ebe8e5..72f4d0ceced 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -2952,5 +2952,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/pages/prices/prices_card.dart b/packages/smooth_app/lib/pages/prices/prices_card.dart index f4475c1e5d7..1337706f7c5 100644 --- a/packages/smooth_app/lib/pages/prices/prices_card.dart +++ b/packages/smooth_app/lib/pages/prices/prices_card.dart @@ -50,18 +50,18 @@ class PricesCard extends StatelessWidget { horizontal: MEDIUM_SPACE, vertical: VERY_SMALL_SPACE, ), - child: const Row( + child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( - 'Preview', - style: TextStyle( + appLocalizations.preview_badge, + style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), - SizedBox(width: SMALL_SPACE), - Lab( + const SizedBox(width: SMALL_SPACE), + const Lab( color: Colors.white, size: 13.0, ), diff --git a/packages/smooth_app/lib/pages/prices/prices_page.dart b/packages/smooth_app/lib/pages/prices/prices_page.dart index c2f9ce579e2..20b68c7623c 100644 --- a/packages/smooth_app/lib/pages/prices/prices_page.dart +++ b/packages/smooth_app/lib/pages/prices/prices_page.dart @@ -1,9 +1,16 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/preferences/user_preferences.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart'; import 'package:smooth_app/helpers/launch_url_helper.dart'; +import 'package:smooth_app/helpers/provider_helper.dart'; import 'package:smooth_app/pages/prices/get_prices_model.dart'; import 'package:smooth_app/pages/prices/product_prices_list.dart'; +import 'package:smooth_app/resources/app_icons.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -48,6 +55,98 @@ class PricesPage extends StatelessWidget { label: Text(appLocalizations.prices_add_a_price), icon: const Icon(Icons.add), ), + bottomNavigationBar: ConsumerFilter( + buildWhen: + (UserPreferences? previousValue, UserPreferences currentValue) => + previousValue?.shouldShowPricesFeedbackForm != + currentValue.shouldShowPricesFeedbackForm, + builder: ( + final BuildContext context, + final UserPreferences userPreferences, + _, + ) { + /*if (!userPreferences.shouldShowPricesFeedbackForm) { + return EMPTY_WIDGET; + }*/ + + return const _PricesFeedbackForm(); + }, + ), + ); + } +} + +class _PricesFeedbackForm extends StatelessWidget { + const _PricesFeedbackForm(); + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final SmoothColorsThemeExtension? themeExtension = + Theme.of(context).extension(); + + return Ink( + width: double.infinity, + height: kBottomNavigationBarHeight, + color: themeExtension!.primaryBlack, + child: IconTheme( + data: const IconThemeData(color: Colors.white), + child: InkWell( + onTap: () async { + LaunchUrlHelper.launchURL( + 'https://forms.gle/Vmh9SR3HhPpjMnVF7', + ); + context.read().markPricesFeedbackFormAsCompleted(); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: MEDIUM_SPACE, + vertical: SMALL_SPACE, + ), + child: Row( + children: [ + ExcludeSemantics( + child: Container( + decoration: BoxDecoration( + color: themeExtension.secondaryNormal, + shape: BoxShape.circle, + ), + child: const AspectRatio( + aspectRatio: 1.0, + child: Lab( + color: Colors.white, + size: 13.0, + ), + ), + ), + ), + const SizedBox(width: SMALL_SPACE), + Expanded( + child: AutoSizeText( + appLocalizations.prices_feedback_form, + maxLines: 2, + style: const TextStyle( + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ), + const SizedBox(width: SMALL_SPACE), + InkWell( + customBorder: const CircleBorder(), + onTap: () => context + .read() + .markPricesFeedbackFormAsCompleted(), + child: const AspectRatio( + aspectRatio: 1.0, + child: CloseButtonIcon(), + ), + ) + ], + ), + ), + ), + ), ); } } From 099391d1432f94f77b11ae4239e297478019f2ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jun 2024 08:31:56 +0200 Subject: [PATCH 48/85] chore(deps): bump toshimaru/auto-author-assign from 2.1.0 to 2.1.1 (#5444) Bumps [toshimaru/auto-author-assign](https://github.com/toshimaru/auto-author-assign) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/toshimaru/auto-author-assign/releases) - [Changelog](https://github.com/toshimaru/auto-author-assign/blob/main/CHANGELOG.md) - [Commits](https://github.com/toshimaru/auto-author-assign/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: toshimaru/auto-author-assign dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/auto-assign-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-assign-pr.yml b/.github/workflows/auto-assign-pr.yml index 762822923e9..a41dafbdb97 100644 --- a/.github/workflows/auto-assign-pr.yml +++ b/.github/workflows/auto-assign-pr.yml @@ -16,5 +16,5 @@ jobs: assign-author: runs-on: ubuntu-latest steps: - - uses: toshimaru/auto-author-assign@v2.1.0 + - uses: toshimaru/auto-author-assign@v2.1.1 From 1c4b95954eda5150fbdb846afa94be8f65ca1d1e Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 28 Jun 2024 09:07:12 +0200 Subject: [PATCH 49/85] fix: Fix performances on the photos gallery (#5447) * Improve performances for the photos gallery * Allow to pass an `ImageSize` to `ProductImageWidget` * Update packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart Co-authored-by: monsieurtanuki --------- Co-authored-by: monsieurtanuki --- .../widgets/images/smooth_image.dart | 38 +++++++++---- .../product_image_gallery_other_view.dart | 12 +++++ .../lib/pages/image/product_image_widget.dart | 54 +++++-------------- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart index 3e8a6be7cf1..95e24525693 100644 --- a/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart +++ b/packages/smooth_app/lib/generic_lib/widgets/images/smooth_image.dart @@ -18,7 +18,16 @@ class SmoothImage extends StatelessWidget { this.fit = BoxFit.cover, this.rounded = true, this.heroTag, - }); + this.cacheWidth, + this.cacheHeight, + }) : assert( + cacheWidth == null || imageProvider is NetworkImage, + 'cacheWidth requires a NetworkImage', + ), + assert( + cacheHeight == null || imageProvider is NetworkImage, + 'cacheHeight requires a NetworkImage', + ); final ImageProvider? imageProvider; final double? height; @@ -28,17 +37,28 @@ class SmoothImage extends StatelessWidget { final BoxFit fit; final String? heroTag; final bool rounded; + final int? cacheWidth; + final int? cacheHeight; @override Widget build(BuildContext context) { - Widget child = imageProvider == null - ? const PictureNotFound() - : Image( - image: imageProvider!, - fit: fit, - loadingBuilder: _loadingBuilder, - errorBuilder: _errorBuilder, - ); + Widget child = switch (imageProvider) { + NetworkImage(url: final String url) => Image.network( + url, + fit: fit, + loadingBuilder: _loadingBuilder, + errorBuilder: _errorBuilder, + cacheWidth: cacheWidth, + cacheHeight: cacheHeight, + ), + ImageProvider() => Image( + image: imageProvider!, + fit: fit, + loadingBuilder: _loadingBuilder, + errorBuilder: _errorBuilder, + ), + _ => const PictureNotFound(), + }; if (heroTag != null) { child = Hero(tag: heroTag!, child: child); diff --git a/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart b/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart index 3f40df632f7..3936ac36b1a 100644 --- a/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart +++ b/packages/smooth_app/lib/pages/image/product_image_gallery_other_view.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; @@ -108,6 +109,8 @@ class _RawGridGallery extends StatelessWidget { @override Widget build(BuildContext context) { final double squareSize = _getSquareSize(context); + final ImageSize? imageSize = _computeImageSize(squareSize); + return SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _columns, @@ -137,6 +140,7 @@ class _RawGridGallery extends StatelessWidget { productImage: productImage, barcode: product.barcode!, squareSize: squareSize, + imageSize: imageSize, ), ), ); @@ -146,4 +150,12 @@ class _RawGridGallery extends StatelessWidget { ), ); } + + ImageSize? _computeImageSize(double squareSize) => [ + ImageSize.THUMB, + ImageSize.SMALL, + ImageSize.DISPLAY + ].firstWhereOrNull( + (ImageSize element) => squareSize <= int.parse(element.number), + ); } diff --git a/packages/smooth_app/lib/pages/image/product_image_widget.dart b/packages/smooth_app/lib/pages/image/product_image_widget.dart index c1448413b52..50dd84ded55 100644 --- a/packages/smooth_app/lib/pages/image/product_image_widget.dart +++ b/packages/smooth_app/lib/pages/image/product_image_widget.dart @@ -11,43 +11,20 @@ import 'package:smooth_app/resources/app_icons.dart'; import 'package:smooth_app/themes/smooth_theme_colors.dart'; /// Displays a product image thumbnail with the upload date on top. -class ProductImageWidget extends StatefulWidget { +class ProductImageWidget extends StatelessWidget { const ProductImageWidget({ required this.productImage, required this.barcode, required this.squareSize, + this.imageSize, }); final ProductImage productImage; final String barcode; final double squareSize; - @override - State createState() => _ProductImageWidgetState(); -} - -class _ProductImageWidgetState extends State { - @override - void initState() { - super.initState(); - _loadImagePalette(); - } - - Future _loadImagePalette() async { - final ColorScheme palette = await ColorScheme.fromImageProvider( - provider: NetworkImage(widget.productImage.getUrl( - widget.barcode, - uriHelper: ProductQuery.uriProductHelper, - ))); - - setState(() { - backgroundColor = palette.primaryContainer; - darkBackground = backgroundColor!.computeLuminance() < 0.5; - }); - } - - Color? backgroundColor; - bool? darkBackground; + /// Allows to fetch the optimized version of the image + final ImageSize? imageSize; @override Widget build(BuildContext context) { @@ -57,20 +34,21 @@ class _ProductImageWidgetState extends State { final DateFormat dateFormat = DateFormat.yMd(ProductQuery.getLanguage().offTag); - darkBackground = darkBackground ?? true; - final Widget image = SmoothImage( - width: widget.squareSize, - height: widget.squareSize, + cacheHeight: + (squareSize * MediaQuery.devicePixelRatioOf(context)).toInt(), + width: squareSize, + height: squareSize, imageProvider: NetworkImage( - widget.productImage.getUrl( - widget.barcode, + productImage.getUrl( + barcode, uriHelper: ProductQuery.uriProductHelper, + imageSize: imageSize, ), ), rounded: false, ); - final DateTime? uploaded = widget.productImage.uploaded; + final DateTime? uploaded = productImage.uploaded; if (uploaded == null) { return image; } @@ -85,7 +63,7 @@ class _ProductImageWidgetState extends State { button: true, child: SmoothCard( padding: EdgeInsets.zero, - color: backgroundColor ?? colors.primaryBlack, + color: colors.primaryBlack, borderRadius: ANGULAR_BORDER_RADIUS, margin: EdgeInsets.zero, child: ClipRRect( @@ -108,11 +86,7 @@ class _ProductImageWidgetState extends State { child: AutoSizeText( date, maxLines: 1, - style: TextStyle( - color: darkBackground! - ? Colors.white - : colors.primaryDark, - ), + style: const TextStyle(color: Colors.white), ), ), if (expired) From 08a8df14f464a6abbe5ec92b99bd84ab6d310687 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 28 Jun 2024 09:07:31 +0200 Subject: [PATCH 50/85] fix: Prices feedback form missing SafeArea-like (#5448) --- packages/smooth_app/lib/pages/prices/prices_page.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/smooth_app/lib/pages/prices/prices_page.dart b/packages/smooth_app/lib/pages/prices/prices_page.dart index 20b68c7623c..ada617b91d9 100644 --- a/packages/smooth_app/lib/pages/prices/prices_page.dart +++ b/packages/smooth_app/lib/pages/prices/prices_page.dart @@ -65,9 +65,9 @@ class PricesPage extends StatelessWidget { final UserPreferences userPreferences, _, ) { - /*if (!userPreferences.shouldShowPricesFeedbackForm) { + if (!userPreferences.shouldShowPricesFeedbackForm) { return EMPTY_WIDGET; - }*/ + } return const _PricesFeedbackForm(); }, @@ -85,10 +85,13 @@ class _PricesFeedbackForm extends StatelessWidget { final SmoothColorsThemeExtension? themeExtension = Theme.of(context).extension(); + final double bottomPadding = MediaQuery.viewPaddingOf(context).bottom; + return Ink( width: double.infinity, - height: kBottomNavigationBarHeight, + height: kBottomNavigationBarHeight + bottomPadding, color: themeExtension!.primaryBlack, + padding: EdgeInsetsDirectional.only(bottom: bottomPadding), child: IconTheme( data: const IconThemeData(color: Colors.white), child: InkWell( @@ -99,7 +102,7 @@ class _PricesFeedbackForm extends StatelessWidget { context.read().markPricesFeedbackFormAsCompleted(); }, child: Padding( - padding: const EdgeInsets.symmetric( + padding: const EdgeInsetsDirectional.symmetric( horizontal: MEDIUM_SPACE, vertical: SMALL_SPACE, ), From 32cab47dc5eee65e9ea528a6ee9958415552ae6a Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 28 Jun 2024 11:07:49 +0200 Subject: [PATCH 51/85] Second method to follow deep links with `LaunchUrlHelper` (#5450) --- .../lib/helpers/launch_url_helper.dart | 18 +++++++++++++++++- .../scan/carousel/main_card/scan_tagline.dart | 5 ++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/smooth_app/lib/helpers/launch_url_helper.dart b/packages/smooth_app/lib/helpers/launch_url_helper.dart index 95a8aff0bcc..3e1264d2f16 100644 --- a/packages/smooth_app/lib/helpers/launch_url_helper.dart +++ b/packages/smooth_app/lib/helpers/launch_url_helper.dart @@ -1,10 +1,26 @@ import 'dart:io'; +import 'package:flutter/widgets.dart'; +import 'package:go_router/go_router.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:url_launcher/url_launcher.dart'; class LaunchUrlHelper { - LaunchUrlHelper._(); + const LaunchUrlHelper._(); + + static Future launchURLAndFollowDeepLinks( + BuildContext context, + String url, + ) async { + assert(url.isNotEmpty); + + if (url.startsWith(RegExp('http(s)?://[a-z]*.openfoodfacts.(net|org)'))) { + AnalyticsHelper.trackOutlink(url: url); + GoRouter.of(context).go(url); + } else { + return launchURL(url); + } + } /// Launches the url in an external browser. static Future launchURL(String url) async { diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart index 6fce8fabb61..d3e029655cf 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart @@ -368,7 +368,10 @@ class _TagLineContentButton extends StatelessWidget { ), ], ), - onPressed: () => LaunchUrlHelper.launchURL(link), + onPressed: () => LaunchUrlHelper.launchURLAndFollowDeepLinks( + context, + link, + ), ); } } From 3a6df6430fcb5bf485dec13bc8814b1abb35bc2f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:31:54 +0200 Subject: [PATCH 52/85] chore(develop): release 4.15.0 (#5106) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ version.txt | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b478ea3793..77f83067321 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,80 @@ # Changelog +## [4.15.0](https://github.com/openfoodfacts/smooth-app/compare/v4.14.0...v4.15.0) (2024-06-28) + + +### Features + +* 5 new icons: chicken / fish / milk / soda happy / soda unhappy ([#5268](https://github.com/openfoodfacts/smooth-app/issues/5268)) ([74cf6c6](https://github.com/openfoodfacts/smooth-app/commit/74cf6c6a2349c5eaa3a599a4556e10aadf39a505)) +* 5079 - new deeplink to the Country Eco-Score ([#5152](https://github.com/openfoodfacts/smooth-app/issues/5152)) ([2ee3cd8](https://github.com/openfoodfacts/smooth-app/commit/2ee3cd840551bc9cc90668b75315cb7cf9b11c67)) +* 5095 - matomo anonymous visitor id now starts with a persistent letter ([#5107](https://github.com/openfoodfacts/smooth-app/issues/5107)) ([f1d0992](https://github.com/openfoodfacts/smooth-app/commit/f1d09923cc0c1c24d6248c4bbc2e34f1eb7469fc)) +* 5099 - new dev mode item to refresh all the products from the server ([#5100](https://github.com/openfoodfacts/smooth-app/issues/5100)) ([c6077dc](https://github.com/openfoodfacts/smooth-app/commit/c6077dce33609e06cd69993cb949d258766d8da5)) +* 5128 - visible dates on raw image grid items ([#5144](https://github.com/openfoodfacts/smooth-app/issues/5144)) ([1922d39](https://github.com/openfoodfacts/smooth-app/commit/1922d39f073c813dde606f9254ca4453279eb56c)) +* 5191 - knowledge panel image card now clickable ([#5220](https://github.com/openfoodfacts/smooth-app/issues/5220)) ([db20b51](https://github.com/openfoodfacts/smooth-app/commit/db20b51cb6dc968a87af2d48956a53fbbdc9536e)) +* 5195 - location search, as a preliminary step ([#5274](https://github.com/openfoodfacts/smooth-app/issues/5274)) ([5a95ca6](https://github.com/openfoodfacts/smooth-app/commit/5a95ca688a99f2e1bb9ac0c7a4718b50227ab2bb)) +* 5195 - new "add one product price" page with background task ([#5292](https://github.com/openfoodfacts/smooth-app/issues/5292)) ([db223b5](https://github.com/openfoodfacts/smooth-app/commit/db223b5db58039d24b6cade67b1ad4a79f8c57bd)) +* 5197 - first product price page ([#5271](https://github.com/openfoodfacts/smooth-app/issues/5271)) ([004ec9c](https://github.com/openfoodfacts/smooth-app/commit/004ec9c411027c9890917d563d970db4d6e1eb5b)) +* 5198 - added a local "latest prices" page ([#5351](https://github.com/openfoodfacts/smooth-app/issues/5351)) ([39c9c43](https://github.com/openfoodfacts/smooth-app/commit/39c9c434b9ebc5a2aef2a85309eb9b8a5ca30a76)) +* 5200 - currency selector ([#5236](https://github.com/openfoodfacts/smooth-app/issues/5236)) ([e3f01ce](https://github.com/openfoodfacts/smooth-app/commit/e3f01ce061b1df91bcdefdc995f4f70c754051a6)) +* 5201 - change currency with country when relevant ([#5238](https://github.com/openfoodfacts/smooth-app/issues/5238)) ([5f7966c](https://github.com/openfoodfacts/smooth-app/commit/5f7966c7f880611d5114876ada463f189cd473b0)) +* 5203 - "add receipt" and "add price tags", even offline or not found ([#5392](https://github.com/openfoodfacts/smooth-app/issues/5392)) ([b9f83c4](https://github.com/openfoodfacts/smooth-app/commit/b9f83c414073e5a0c42b86f3226d6e2ee3c50bad)) +* 5204 - multi-product price addition ([#5375](https://github.com/openfoodfacts/smooth-app/issues/5375)) ([b300955](https://github.com/openfoodfacts/smooth-app/commit/b3009557eca4aba1f184aac1abd56250e36c5067)) +* 5204 - preliminary step for multi-product price addition ([#5367](https://github.com/openfoodfacts/smooth-app/issues/5367)) ([7bf53e8](https://github.com/openfoodfacts/smooth-app/commit/7bf53e894dba429dc9e7ba8d0f2dca4176fd6181)) +* 5205 - added 4 links to prices app ([#5329](https://github.com/openfoodfacts/smooth-app/issues/5329)) ([27259c0](https://github.com/openfoodfacts/smooth-app/commit/27259c0b3c271e30fd299d114ac5ff389f78263f)) +* 5205 - added a "My prices" item linking to the web app ([#5317](https://github.com/openfoodfacts/smooth-app/issues/5317)) ([722c2f4](https://github.com/openfoodfacts/smooth-app/commit/722c2f498d6dbc8190ee9c50def38e9ffc3799c6)) +* 5205 - new "my prices" page ([#5347](https://github.com/openfoodfacts/smooth-app/issues/5347)) ([13072eb](https://github.com/openfoodfacts/smooth-app/commit/13072eb0864d79a5e9775ef42de6fe618816edc0)) +* 5207 - new "My proofs" and "Proof" pages ([#5389](https://github.com/openfoodfacts/smooth-app/issues/5389)) ([4fbf020](https://github.com/openfoodfacts/smooth-app/commit/4fbf0203acb366f6d797b20a4b22f3a2c3a89523)) +* 5301 - added an erasing tool for proofs ([#5341](https://github.com/openfoodfacts/smooth-app/issues/5341)) ([036bda1](https://github.com/openfoodfacts/smooth-app/commit/036bda1fec0371b690b8e4488a5626439bc3c24c)) +* 5301 - price proofs can be cropped and will be displayed ([#5305](https://github.com/openfoodfacts/smooth-app/issues/5305)) ([529fe8f](https://github.com/openfoodfacts/smooth-app/commit/529fe8f5e1e18e9b52782e66e6dd8072f2fed11b)) +* 5318 - added a "price privacy warning" dialog ([#5343](https://github.com/openfoodfacts/smooth-app/issues/5343)) ([e94d61f](https://github.com/openfoodfacts/smooth-app/commit/e94d61fa11ef9e210147f91034431296180a87b7)) +* 5323 - generic way to display product images, with timestamp ([#5333](https://github.com/openfoodfacts/smooth-app/issues/5333)) ([c26528c](https://github.com/openfoodfacts/smooth-app/commit/c26528c9b9a9243800180ade71ac4f5b9b79db6e)) +* 5352 - now opening the related product price page from count button ([#5353](https://github.com/openfoodfacts/smooth-app/issues/5353)) ([536eae4](https://github.com/openfoodfacts/smooth-app/commit/536eae48b1d780e9d77d08c101dec271f32300fd)) +* A feedback form for the prices page ([#5442](https://github.com/openfoodfacts/smooth-app/issues/5442)) ([b110334](https://github.com/openfoodfacts/smooth-app/commit/b110334c3d577683969270baddae6e6d9ad9046b)) +* Add NutriScore V2 into cache + semantics ([#5264](https://github.com/openfoodfacts/smooth-app/issues/5264)) ([d2d8d0a](https://github.com/openfoodfacts/smooth-app/commit/d2d8d0a6df41da1551f9728808b5da8194ef1c08)) +* added deeplinking for the sign up page [#4169](https://github.com/openfoodfacts/smooth-app/issues/4169) ([#5332](https://github.com/openfoodfacts/smooth-app/issues/5332)) ([2e44edb](https://github.com/openfoodfacts/smooth-app/commit/2e44edb5669eedfb8331d6b7fd06a8dacc2172be)) +* Better error message for search screen ([#5298](https://github.com/openfoodfacts/smooth-app/issues/5298)) ([4b6ed1e](https://github.com/openfoodfacts/smooth-app/commit/4b6ed1e8b66e64d0af7a49f7f3ae13afab35c28a)) +* Crop page: increase paddings ([#5279](https://github.com/openfoodfacts/smooth-app/issues/5279)) ([ebb90b1](https://github.com/openfoodfacts/smooth-app/commit/ebb90b171a87657b7ab6ac5f8aefca74211908ea)) +* currency symbols ([#5311](https://github.com/openfoodfacts/smooth-app/issues/5311)) ([4db1d6c](https://github.com/openfoodfacts/smooth-app/commit/4db1d6c25cbb4b2f4b2b24c201987d4eb9066536)) +* Custom domain + environment support for the TagLine ([#5364](https://github.com/openfoodfacts/smooth-app/issues/5364)) ([08071d2](https://github.com/openfoodfacts/smooth-app/commit/08071d273b048753b1a1c1d9ada51d224c60873c)) +* Extract ingredients/packaging: loading / loaded / extracting states ([#5384](https://github.com/openfoodfacts/smooth-app/issues/5384)) ([65ce9c4](https://github.com/openfoodfacts/smooth-app/commit/65ce9c45ce40ab6f2caa7dfadc57be4092174e37)) +* Guide for Nutri-Score V2 ([#5273](https://github.com/openfoodfacts/smooth-app/issues/5273)) ([dbd23f5](https://github.com/openfoodfacts/smooth-app/commit/dbd23f50f8b3a00974ffd37bf3ce491b41aad9b1)) +* Improve photo gallery accessibility + internationalization ([#5366](https://github.com/openfoodfacts/smooth-app/issues/5366)) ([64d38f1](https://github.com/openfoodfacts/smooth-app/commit/64d38f17dafb715499857fc4611bb3f25cdbb524)) +* Inject all colors from palette in an extension ([#5267](https://github.com/openfoodfacts/smooth-app/issues/5267)) ([f9797bc](https://github.com/openfoodfacts/smooth-app/commit/f9797bc8325f9300954cf0cbfb9f7d6aed8c4cac)) +* Knowledge Panel details page accessibility improvements ([#5290](https://github.com/openfoodfacts/smooth-app/issues/5290)) ([44e4774](https://github.com/openfoodfacts/smooth-app/commit/44e47749367d74b7b9cf19a795a848f6e9471b88)) +* OCR: Better explain why the photo is still loading ([#5426](https://github.com/openfoodfacts/smooth-app/issues/5426)) ([ad9c06e](https://github.com/openfoodfacts/smooth-app/commit/ad9c06eaf8d69989afde97181ef5ac1c885161f5)) +* prices - barcode reader for additional products ([#5381](https://github.com/openfoodfacts/smooth-app/issues/5381)) ([35a4ab0](https://github.com/openfoodfacts/smooth-app/commit/35a4ab03c027406af6946ed024f7d53c3e86d322)) +* prices - top contributors now within the app ([#5383](https://github.com/openfoodfacts/smooth-app/issues/5383)) ([7809854](https://github.com/openfoodfacts/smooth-app/commit/780985462a773ca63fd7db8ed101541347fd3441)) +* Snap scrolling for guides ([#5283](https://github.com/openfoodfacts/smooth-app/issues/5283)) ([8338e90](https://github.com/openfoodfacts/smooth-app/commit/8338e90aac218441e168c376db3fd105b50e8324)) +* Spellchecker for OCR screens ([#5409](https://github.com/openfoodfacts/smooth-app/issues/5409)) ([f6ec9df](https://github.com/openfoodfacts/smooth-app/commit/f6ec9dfee59f2a622ee109eea90f1b504dfddf3d)) +* Tagline V3 ([#5350](https://github.com/openfoodfacts/smooth-app/issues/5350)) ([41abf73](https://github.com/openfoodfacts/smooth-app/commit/41abf730fe09139ee68ce765eff00a72f47d9999)) + + +### Bug Fixes + +* `ThemeProvider` properly resync the theme ([#5363](https://github.com/openfoodfacts/smooth-app/issues/5363)) ([b5b308c](https://github.com/openfoodfacts/smooth-app/commit/b5b308c99d8d73ac7218efd82c839a00348454b5)) +* 2 bugfixes for the tagline (empty content + image in error) ([#5421](https://github.com/openfoodfacts/smooth-app/issues/5421)) ([4deb0b4](https://github.com/openfoodfacts/smooth-app/commit/4deb0b42a47db7dee4cb8025a20ad3e6c29fed03)) +* 4957 - SVG icons are now correctly refreshed when their URL change ([#5133](https://github.com/openfoodfacts/smooth-app/issues/5133)) ([6ac205c](https://github.com/openfoodfacts/smooth-app/commit/6ac205cc4b8adb8c49a1cbb5a4c31a20edfbe983)) +* 5102 - fixed the path of the database to backup ([#5103](https://github.com/openfoodfacts/smooth-app/issues/5103)) ([cd563f5](https://github.com/openfoodfacts/smooth-app/commit/cd563f5d12627f86d253d6d6737a6d9b83342147)) +* 5104 - fixed the position of the "Failed lookup" string ([#5105](https://github.com/openfoodfacts/smooth-app/issues/5105)) ([98de444](https://github.com/openfoodfacts/smooth-app/commit/98de4446344d825aa9aae5ee397c65b4ec16da44)) +* 5121 - more relevant choice of nutrients to display (edit page) ([#5150](https://github.com/openfoodfacts/smooth-app/issues/5150)) ([3217dfe](https://github.com/openfoodfacts/smooth-app/commit/3217dfe63e6cd51cc98b599c327694a936ab81ed)) +* 5145 - bold style for unknown ingredients in KP ([#5149](https://github.com/openfoodfacts/smooth-app/issues/5149)) ([0e3eee2](https://github.com/openfoodfacts/smooth-app/commit/0e3eee2c3ed2aa6482a3287005f5fa58a7223576)) +* 5217 - no check on cookie as it's always null ([#5222](https://github.com/openfoodfacts/smooth-app/issues/5222)) ([d744fab](https://github.com/openfoodfacts/smooth-app/commit/d744fab3344fed5e86caf9be47c01429d18356d9)) +* 5221 - downgrade to previous connectivity_plus package version ([#5223](https://github.com/openfoodfacts/smooth-app/issues/5223)) ([2594b38](https://github.com/openfoodfacts/smooth-app/commit/2594b38fec4b2fa470b6cd0e80acaaa7cfe4729d)) +* 5247 - now "unselect"ing for the correct language ([#5266](https://github.com/openfoodfacts/smooth-app/issues/5266)) ([8758b0e](https://github.com/openfoodfacts/smooth-app/commit/8758b0e818922d7adc1579deac37fb0b41cd86c0)) +* 5288 - added svg files to cache ([#5299](https://github.com/openfoodfacts/smooth-app/issues/5299)) ([dcd70ea](https://github.com/openfoodfacts/smooth-app/commit/dcd70eacc417f48daa3870fae6dceb5e78408a11)) +* 5330 - updated link to the skill pool ([#5334](https://github.com/openfoodfacts/smooth-app/issues/5334)) ([1ce24e8](https://github.com/openfoodfacts/smooth-app/commit/1ce24e8f2d31dbf96b77c2a0530dfcaf09e8a20d)) +* 5345 ([#5346](https://github.com/openfoodfacts/smooth-app/issues/5346)) ([2dd4575](https://github.com/openfoodfacts/smooth-app/commit/2dd4575b96baa33fb659bc4fd56478906445740f)) +* 5371 - less ambiguous currency symbol ([#5376](https://github.com/openfoodfacts/smooth-app/issues/5376)) ([18505dd](https://github.com/openfoodfacts/smooth-app/commit/18505ddc0e09ec7bf6f048dd7b0f1eb7a33a04db)) +* adjusting onTap call ([#5113](https://github.com/openfoodfacts/smooth-app/issues/5113)) ([f57c0c0](https://github.com/openfoodfacts/smooth-app/commit/f57c0c00c72f341595d036a7f94bc9c1d8951520)) +* Fix issues with themes ([#5410](https://github.com/openfoodfacts/smooth-app/issues/5410)) ([6026fbc](https://github.com/openfoodfacts/smooth-app/commit/6026fbc91bdad67d84cdffd8c8cbefa1b15914aa)) +* Fix performances on the photos gallery ([#5447](https://github.com/openfoodfacts/smooth-app/issues/5447)) ([1c4b959](https://github.com/openfoodfacts/smooth-app/commit/1c4b95954eda5150fbdb846afa94be8f65ca1d1e)) +* Guide: Rewrite newline character from translations ([#5365](https://github.com/openfoodfacts/smooth-app/issues/5365)) ([f5973da](https://github.com/openfoodfacts/smooth-app/commit/f5973da76964a31a498e1e546f8566948b3b44fa)) +* Prices feedback form missing SafeArea-like ([#5448](https://github.com/openfoodfacts/smooth-app/issues/5448)) ([08a8df1](https://github.com/openfoodfacts/smooth-app/commit/08a8df14f464a6abbe5ec92b99bd84ab6d310687)) +* RankingFloatingActionButton partially off-screen for some translations ([#5117](https://github.com/openfoodfacts/smooth-app/issues/5117)) ([9075fdc](https://github.com/openfoodfacts/smooth-app/commit/9075fdc3430fbb37351f8e42992feaca36e62927)) +* Support for photos in a different language than the default one (green buttons) ([#5278](https://github.com/openfoodfacts/smooth-app/issues/5278)) ([ffe90e7](https://github.com/openfoodfacts/smooth-app/commit/ffe90e76528d1dcb3731ddd87ec4d6871c18a7d1)) +* Update dependabot.yml ([49998ec](https://github.com/openfoodfacts/smooth-app/commit/49998eca6a20663604eff5d6592c4681f2468ad4)) +* Update tagline_provider.dart ([e4cb2f2](https://github.com/openfoodfacts/smooth-app/commit/e4cb2f26a10cf7a8b269c03bfadb82ccaef40b4e)) + ## [4.14.0](https://github.com/openfoodfacts/smooth-app/compare/v4.13.0...v4.14.0) (2024-03-02) diff --git a/version.txt b/version.txt index c412a4e2e1e..5c517bf11d5 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -4.14.0 +4.15.0 From 8c10181accf33b84a452e8cd4ccd833160b6cb80 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 1 Jul 2024 09:37:06 +0200 Subject: [PATCH 53/85] bump in_app_review dependency (#5452) --- packages/app_store/apple_app_store/pubspec.yaml | 4 ++-- packages/app_store/google_play/pubspec.yaml | 4 ++-- packages/app_store/shared/pubspec.yaml | 2 +- packages/app_store/uri_store/pubspec.yaml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/app_store/apple_app_store/pubspec.yaml b/packages/app_store/apple_app_store/pubspec.yaml index c3317039f29..ed12d33a943 100644 --- a/packages/app_store/apple_app_store/pubspec.yaml +++ b/packages/app_store/apple_app_store/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: flutter: sdk: flutter - in_app_review: 2.0.4 + in_app_review: 2.0.9 app_store_shared: path: ../shared @@ -18,6 +18,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: 2.0.2 + flutter_lints: 2.0.3 openfoodfacts_flutter_lints: git: https://github.com/openfoodfacts/openfoodfacts_flutter_lints.git \ No newline at end of file diff --git a/packages/app_store/google_play/pubspec.yaml b/packages/app_store/google_play/pubspec.yaml index e906b0e2f76..9f6c287d4fa 100644 --- a/packages/app_store/google_play/pubspec.yaml +++ b/packages/app_store/google_play/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: flutter: sdk: flutter - in_app_review: 2.0.4 + in_app_review: 2.0.9 app_store_shared: path: ../shared @@ -18,7 +18,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: 2.0.2 + flutter_lints: 2.0.3 openfoodfacts_flutter_lints: git: https://github.com/openfoodfacts/openfoodfacts_flutter_lints.git diff --git a/packages/app_store/shared/pubspec.yaml b/packages/app_store/shared/pubspec.yaml index ea7e215339c..4978f448a6c 100644 --- a/packages/app_store/shared/pubspec.yaml +++ b/packages/app_store/shared/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: 2.0.2 + flutter_lints: 2.0.3 openfoodfacts_flutter_lints: git: https://github.com/openfoodfacts/openfoodfacts_flutter_lints.git diff --git a/packages/app_store/uri_store/pubspec.yaml b/packages/app_store/uri_store/pubspec.yaml index 7ed3f6a6611..5b5d99659be 100644 --- a/packages/app_store/uri_store/pubspec.yaml +++ b/packages/app_store/uri_store/pubspec.yaml @@ -18,6 +18,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: 2.0.2 + flutter_lints: 2.0.3 openfoodfacts_flutter_lints: git: https://github.com/openfoodfacts/openfoodfacts_flutter_lints.git \ No newline at end of file From 9e211ca29c5caf33c5ca7401ab92235ccb81cb27 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 4 Jul 2024 09:10:34 +0200 Subject: [PATCH 54/85] chore: Bump Flutter version to 3.22 (#5458) * Bump Flutter version to 3.22 * Migrate Material properties --- README.md | 2 +- flutter-version.txt | 2 +- .../app_store/apple_app_store/pubspec.yaml | 2 +- packages/app_store/google_play/pubspec.yaml | 2 +- packages/app_store/shared/pubspec.yaml | 2 +- packages/app_store/uri_store/pubspec.yaml | 2 +- packages/scanner/ml_kit/pubspec.yaml | 2 +- packages/scanner/shared/pubspec.yaml | 2 +- packages/scanner/zxing/pubspec.yaml | 2 +- .../buttons/smooth_simple_button.dart | 10 ++-- .../dialogs/smooth_alert_dialog.dart | 2 +- .../question_answers_options.dart | 4 +- .../smooth_app/lib/pages/image_crop_page.dart | 6 +-- .../pages/locations/location_query_page.dart | 4 +- .../onboarding/onboarding_bottom_bar.dart | 7 ++- .../v2/onboarding_bottom_hills.dart | 16 +++--- .../preferences/user_preferences_account.dart | 4 +- .../preferences/user_preferences_connect.dart | 2 +- .../preferences/user_preferences_rate_us.dart | 4 +- .../user_preferences_share_with_friends.dart | 4 +- .../product/common/product_list_page.dart | 2 +- .../lib/pages/product/edit_image_button.dart | 8 +-- .../pages/product/edit_new_packagings.dart | 2 +- .../pages/product/edit_ocr/edit_ocr_page.dart | 2 +- .../lib/pages/product/new_product_page.dart | 4 +- .../nutrition_add_nutrient_button.dart | 2 +- .../pages/product/nutrition_page_loaded.dart | 2 +- .../product/product_incomplete_card.dart | 6 +-- .../product_question_answers_options.dart | 2 +- .../lib/pages/scan/scan_header.dart | 2 +- .../smooth_app/lib/pages/scan/scan_page.dart | 2 +- .../lib/pages/scan/search_history_view.dart | 4 +- .../user_management/forgot_password_page.dart | 5 +- .../lib/pages/user_management/login_page.dart | 18 +++---- .../pages/user_management/sign_up_page.dart | 30 +++++------ .../lib/smooth_category_picker_example.dart | 5 +- .../smooth_app/lib/themes/color_schemes.dart | 16 ++---- .../smooth_app/lib/themes/smooth_theme.dart | 51 +++++++++---------- .../ranking_floating_action_button.dart | 2 +- packages/smooth_app/pubspec.lock | 34 ++++++------- packages/smooth_app/pubspec.yaml | 4 +- 41 files changed, 137 insertions(+), 147 deletions(-) diff --git a/README.md b/README.md index 1a81ca581a6..d8a99c424d2 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ - Make sure you have installed flutter and all the requirements - [Official flutter installation guide](https://docs.flutter.dev/get-started/install) -- Currently, the app uses the latest stable version of Flutter (3.19.x). +- Currently, the app uses the following version of Flutter (3.22.x). We have predefined run configurations for Android Studio and Visual Studio Code diff --git a/flutter-version.txt b/flutter-version.txt index 0bc8e967b83..dbc9520ba41 100644 --- a/flutter-version.txt +++ b/flutter-version.txt @@ -1 +1 @@ -3.19.5 \ No newline at end of file +3.22.2 \ No newline at end of file diff --git a/packages/app_store/apple_app_store/pubspec.yaml b/packages/app_store/apple_app_store/pubspec.yaml index ed12d33a943..0a6b0494448 100644 --- a/packages/app_store/apple_app_store/pubspec.yaml +++ b/packages/app_store/apple_app_store/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/google_play/pubspec.yaml b/packages/app_store/google_play/pubspec.yaml index 9f6c287d4fa..54161b2443e 100644 --- a/packages/app_store/google_play/pubspec.yaml +++ b/packages/app_store/google_play/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/shared/pubspec.yaml b/packages/app_store/shared/pubspec.yaml index 4978f448a6c..86fec92bc7f 100644 --- a/packages/app_store/shared/pubspec.yaml +++ b/packages/app_store/shared/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/uri_store/pubspec.yaml b/packages/app_store/uri_store/pubspec.yaml index 5b5d99659be..1e661bdb92a 100644 --- a/packages/app_store/uri_store/pubspec.yaml +++ b/packages/app_store/uri_store/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/ml_kit/pubspec.yaml b/packages/scanner/ml_kit/pubspec.yaml index 5b69d47d97a..753b8caafd2 100644 --- a/packages/scanner/ml_kit/pubspec.yaml +++ b/packages/scanner/ml_kit/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/shared/pubspec.yaml b/packages/scanner/shared/pubspec.yaml index 7730dc8abaf..7fa9a28d1f0 100644 --- a/packages/scanner/shared/pubspec.yaml +++ b/packages/scanner/shared/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/zxing/pubspec.yaml b/packages/scanner/zxing/pubspec.yaml index 76b0988cd50..0e32939a7b4 100644 --- a/packages/scanner/zxing/pubspec.yaml +++ b/packages/scanner/zxing/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart b/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart index cc978a528ab..52dae9e156d 100644 --- a/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart +++ b/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart @@ -33,19 +33,19 @@ class SmoothSimpleButton extends StatelessWidget { style: ButtonStyle( backgroundColor: buttonColor == null ? null - : MaterialStateProperty.all(buttonColor!), - shape: MaterialStateProperty.all( + : WidgetStateProperty.all(buttonColor!), + shape: WidgetStateProperty.all( RoundedRectangleBorder(borderRadius: borderRadius), ), overlayColor: context.read().isAmoledTheme - ? MaterialStateProperty.resolveWith((Set states) { - return states.contains(MaterialState.pressed) + ? WidgetStateProperty.resolveWith((Set states) { + return states.contains(WidgetState.pressed) ? Theme.of(context).colorScheme.primary.withOpacity(0.3) : null; }) : null, side: context.read().isAmoledTheme - ? MaterialStateProperty.all( + ? WidgetStateProperty.all( const BorderSide(color: Colors.white), ) : null, diff --git a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart index f267cc1dba6..0d03fca3a89 100644 --- a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart +++ b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart @@ -213,7 +213,7 @@ class _SmoothDialogTitle extends StatelessWidget { ], ), ), - Divider(color: Theme.of(context).colorScheme.onBackground), + Divider(color: Theme.of(context).colorScheme.onSurface), const SizedBox(height: 12), ], ); diff --git a/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart b/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart index dcea8df0085..e1ee8172f20 100755 --- a/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart +++ b/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart @@ -108,8 +108,8 @@ class QuestionAnswersOptions extends StatelessWidget { child: TextButton.icon( onPressed: () => onAnswer(insightAnnotation), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(backgroundColor), - shape: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all(backgroundColor), + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/image_crop_page.dart b/packages/smooth_app/lib/pages/image_crop_page.dart index 614b7431c0a..67f902807c1 100644 --- a/packages/smooth_app/lib/pages/image_crop_page.dart +++ b/packages/smooth_app/lib/pages/image_crop_page.dart @@ -225,13 +225,13 @@ class _ImageSourceButton extends StatelessWidget { child: OutlinedButton( onPressed: onPressed, style: ButtonStyle( - side: MaterialStatePropertyAll( + side: WidgetStatePropertyAll( BorderSide(color: primaryColor), ), - padding: const MaterialStatePropertyAll( + padding: const WidgetStatePropertyAll( EdgeInsets.symmetric(vertical: LARGE_SPACE), ), - shape: MaterialStatePropertyAll( + shape: WidgetStatePropertyAll( RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, side: BorderSide(color: primaryColor), diff --git a/packages/smooth_app/lib/pages/locations/location_query_page.dart b/packages/smooth_app/lib/pages/locations/location_query_page.dart index 250f35e0172..61524e27a5e 100644 --- a/packages/smooth_app/lib/pages/locations/location_query_page.dart +++ b/packages/smooth_app/lib/pages/locations/location_query_page.dart @@ -110,8 +110,8 @@ class _LocationQueryPageState extends State data: ListTileThemeData( titleTextStyle: const TextStyle(fontSize: 20.0), minLeadingWidth: 18.0, - iconColor: Theme.of(context).colorScheme.onBackground, - textColor: Theme.of(context).colorScheme.onBackground, + iconColor: Theme.of(context).colorScheme.onSurface, + textColor: Theme.of(context).colorScheme.onSurface, ), child: ListView.builder( itemBuilder: (BuildContext context, int index) => diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart index 57e9b0abf83..089aed5f5ef 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart @@ -90,12 +90,11 @@ class OnboardingBottomButton extends StatelessWidget { key: nextKey, onPressed: onPressed, style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(backgroundColor), + backgroundColor: WidgetStateProperty.all(backgroundColor), overlayColor: backgroundColor == Colors.white - ? MaterialStateProperty.all( - Theme.of(context).splashColor) + ? WidgetStateProperty.all(Theme.of(context).splashColor) : null, - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(40))), ), diff --git a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart index 49b3b784299..e8ecaa7c70b 100644 --- a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart +++ b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart @@ -62,10 +62,10 @@ class OnboardingBottomHills extends StatelessWidget { end: 15.0, child: TextButton( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( Colors.white, ), - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsetsDirectional.only( start: LARGE_SPACE + 1.0, end: LARGE_SPACE, @@ -73,20 +73,20 @@ class OnboardingBottomHills extends StatelessWidget { bottom: SMALL_SPACE, ), ), - elevation: MaterialStateProperty.all(4.0), - iconColor: MaterialStateProperty.all( + elevation: WidgetStateProperty.all(4.0), + iconColor: WidgetStateProperty.all( colors.orange, ), - foregroundColor: MaterialStateProperty.all( + foregroundColor: WidgetStateProperty.all( colors.orange, ), - iconSize: MaterialStateProperty.all(21.0), - shape: MaterialStateProperty.all( + iconSize: WidgetStateProperty.all(21.0), + shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), ), ), - shadowColor: MaterialStateProperty.all( + shadowColor: WidgetStateProperty.all( Colors.black.withOpacity(0.50), ), ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart index 94ad1b57cb3..3121ddff96c 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart @@ -147,10 +147,10 @@ class UserPreferencesAccount extends AbstractUserPreferences { child: ElevatedButton( onPressed: () async => _goToLoginPage(), style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, themeData.buttonTheme.height + 10), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart index 8704baf50fa..1e4e0f169f5 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart @@ -111,7 +111,7 @@ class UserPreferencesConnect extends AbstractUserPreferences { 'assets/preferences/x-logo.svg', width: DEFAULT_ICON_SIZE, colorFilter: ui.ColorFilter.mode( - Theme.of(context).colorScheme.onBackground, + Theme.of(context).colorScheme.onSurface, ui.BlendMode.srcIn, ), package: AppHelper.APP_PACKAGE, diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart index cba7fc5eefe..3600c1330ab 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart @@ -50,10 +50,10 @@ class UserPreferencesRateUs extends StatelessWidget { content: Text( appLocalizations.error_occurred, textAlign: TextAlign.center, - style: TextStyle(color: themeData.colorScheme.background), + style: TextStyle(color: themeData.colorScheme.surface), ), behavior: SnackBarBehavior.floating, - backgroundColor: themeData.colorScheme.onBackground, + backgroundColor: themeData.colorScheme.onSurface, ), ); } diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart index 6e9875ff5c3..44840fa1c28 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart @@ -44,11 +44,11 @@ class UserPreferencesShareWithFriends extends StatelessWidget { appLocalizations.error, textAlign: TextAlign.center, style: TextStyle( - color: themeData.colorScheme.background, + color: themeData.colorScheme.surface, ), ), behavior: SnackBarBehavior.floating, - backgroundColor: themeData.colorScheme.onBackground, + backgroundColor: themeData.colorScheme.onSurface, ), ); } diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index d831b6c70bc..59d9b4e671a 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -267,7 +267,7 @@ class _ProductListPageState extends State appLocalizations.product_list_empty_message, textAlign: TextAlign.center, style: themeData.textTheme.bodyMedium?.apply( - color: themeData.colorScheme.onBackground, + color: themeData.colorScheme.onSurface, ), ), EMPTY_WIDGET, diff --git a/packages/smooth_app/lib/pages/product/edit_image_button.dart b/packages/smooth_app/lib/pages/product/edit_image_button.dart index bc644102552..dd30c53526f 100644 --- a/packages/smooth_app/lib/pages/product/edit_image_button.dart +++ b/packages/smooth_app/lib/pages/product/edit_image_button.dart @@ -33,20 +33,20 @@ class EditImageButton extends StatelessWidget { child: OutlinedButton.icon( icon: Icon(iconData), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(colorScheme.onPrimary), - shape: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all(colorScheme.onPrimary), + shape: WidgetStateProperty.all( const RoundedRectangleBorder(borderRadius: ROUNDED_BORDER_RADIUS), ), side: borderWidth == null ? null - : MaterialStateBorderSide.resolveWith( + : WidgetStateBorderSide.resolveWith( (_) => BorderSide( color: colorScheme.primary, width: borderWidth!, ), ), padding: _centerContent - ? MaterialStateProperty.all( + ? WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: LARGE_SPACE, ), diff --git a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart index 6c4e248066c..4c0a003929b 100644 --- a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart +++ b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart @@ -324,7 +324,7 @@ Color _getSmoothCardColorAlternate(final BuildContext context, int index) { if (index.isOdd) { cardColor = PRIMARY_GREY_COLOR; } else { - cardColor = darkColorScheme.background; + cardColor = darkColorScheme.surface; } } diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index 1f737bc5744..d78a52cce5e 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -294,7 +294,7 @@ class _EditOcrPageState extends State with UpToDateMixin { flex: 1, child: DecoratedBox( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadiusDirectional.only( topStart: ANGULAR_RADIUS, topEnd: ANGULAR_RADIUS, diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index ee44bec4fb5..e20901edfa2 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -416,11 +416,11 @@ class _ProductPageState extends State ), child: ElevatedButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsets.symmetric( horizontal: VERY_LARGE_SPACE, vertical: MEDIUM_SPACE), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart b/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart index 86b1a5dea6a..afa30d2b80d 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart @@ -99,7 +99,7 @@ class NutritionAddNutrientButton extends StatelessWidget { } }, style: ButtonStyle( - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, side: BorderSide.none, diff --git a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart index 3a872cbbf39..6fed13681ec 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart @@ -322,7 +322,7 @@ class _NutritionPageLoadedState extends State value: _nutritionContainer.noNutritionData, onChanged: (final bool value) => setState(() => _nutritionContainer.noNutritionData = value), - trackColor: MaterialStateProperty.all( + trackColor: WidgetStateProperty.all( Theme.of(context).colorScheme.onPrimary), ), ), diff --git a/packages/smooth_app/lib/pages/product/product_incomplete_card.dart b/packages/smooth_app/lib/pages/product/product_incomplete_card.dart index ceba846b333..c60c7897639 100644 --- a/packages/smooth_app/lib/pages/product/product_incomplete_card.dart +++ b/packages/smooth_app/lib/pages/product/product_incomplete_card.dart @@ -111,13 +111,13 @@ class ProductIncompleteCard extends StatelessWidget { ), ), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( colorScheme.primary, ), - foregroundColor: MaterialStateProperty.all( + foregroundColor: WidgetStateProperty.all( colorScheme.onPrimary, ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder(borderRadius: ANGULAR_BORDER_RADIUS), ), ), diff --git a/packages/smooth_app/lib/pages/product/product_question_answers_options.dart b/packages/smooth_app/lib/pages/product/product_question_answers_options.dart index efeac877bd0..d9e1c31e72a 100644 --- a/packages/smooth_app/lib/pages/product/product_question_answers_options.dart +++ b/packages/smooth_app/lib/pages/product/product_question_answers_options.dart @@ -91,7 +91,7 @@ class ProductQuestionAnswersOptions extends StatelessWidget { child: TextButton( onPressed: () => onAnswer(insightAnnotation), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(backgroundColor), + backgroundColor: WidgetStateProperty.all(backgroundColor), ), child: Text( buttonText, diff --git a/packages/smooth_app/lib/pages/scan/scan_header.dart b/packages/smooth_app/lib/pages/scan/scan_header.dart index ab419653504..53cbe5bbb6e 100644 --- a/packages/smooth_app/lib/pages/scan/scan_header.dart +++ b/packages/smooth_app/lib/pages/scan/scan_header.dart @@ -24,7 +24,7 @@ class _ScanHeaderState extends State { final ContinuousScanModel model = context.watch(); final ButtonStyle buttonStyle = ButtonStyle( - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(18.0)), ), diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index f1a4f4401ea..26f22f14e30 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -64,7 +64,7 @@ class _ScanPageState extends State { color: Colors.white, child: SafeArea( child: Container( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Column( children: [ if (hasACamera) diff --git a/packages/smooth_app/lib/pages/scan/search_history_view.dart b/packages/smooth_app/lib/pages/scan/search_history_view.dart index 975da30935f..a4b0a94507a 100644 --- a/packages/smooth_app/lib/pages/scan/search_history_view.dart +++ b/packages/smooth_app/lib/pages/scan/search_history_view.dart @@ -46,8 +46,8 @@ class _SearchHistoryViewState extends State { data: ListTileThemeData( titleTextStyle: const TextStyle(fontSize: 20.0), minLeadingWidth: 18.0, - iconColor: Theme.of(context).colorScheme.onBackground, - textColor: Theme.of(context).colorScheme.onBackground, + iconColor: Theme.of(context).colorScheme.onSurface, + textColor: Theme.of(context).colorScheme.onSurface, ), child: ListView.builder( itemBuilder: (BuildContext context, int i) { diff --git a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart index 028ad5d5f38..42108e73d1e 100644 --- a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart +++ b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart @@ -150,11 +150,10 @@ class _ForgotPasswordPageState extends State } }, style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: - MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/user_management/login_page.dart b/packages/smooth_app/lib/pages/user_management/login_page.dart index fbd7e963e49..cbda47ad48b 100644 --- a/packages/smooth_app/lib/pages/user_management/login_page.dart +++ b/packages/smooth_app/lib/pages/user_management/login_page.dart @@ -221,12 +221,12 @@ class _LoginPageState extends State with TraceableClientMixin { ElevatedButton( onPressed: () => _login(context), style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: MaterialStateProperty.all< - RoundedRectangleBorder>( + shape: + WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -249,14 +249,14 @@ class _LoginPageState extends State with TraceableClientMixin { //Forgot password TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: 10.0, horizontal: VERY_LARGE_SPACE, ), ), shape: - MaterialStateProperty.all( + WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -304,15 +304,15 @@ class _LoginPageState extends State with TraceableClientMixin { } }, style: ButtonStyle( - side: MaterialStateProperty.all( + side: WidgetStateProperty.all( BorderSide( color: theme.colorScheme.primary, width: 2.0), ), - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height), ), - shape: MaterialStateProperty.all< - RoundedRectangleBorder>( + shape: + WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart index 48f2713516f..8bbd6b10238 100644 --- a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart +++ b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart @@ -56,11 +56,11 @@ class _SignUpPageState extends State with TraceableClientMixin { final AppLocalizations appLocalizations = AppLocalizations.of(context); final Size size = MediaQuery.sizeOf(context); - Color getCheckBoxColor(Set states) { - const Set interactiveStates = { - MaterialState.pressed, - MaterialState.hovered, - MaterialState.focused, + Color getCheckBoxColor(Set states) { + const Set interactiveStates = { + WidgetState.pressed, + WidgetState.hovered, + WidgetState.focused, }; if (states.any(interactiveStates.contains)) { return theme.colorScheme.onSurface; @@ -236,14 +236,14 @@ class _SignUpPageState extends State with TraceableClientMixin { child: Checkbox( value: _foodProducer, fillColor: - MaterialStateProperty.resolveWith(getCheckBoxColor), + WidgetStateProperty.resolveWith(getCheckBoxColor), onChanged: (_) {}, ), ), title: Text( appLocalizations.sign_up_page_producer_checkbox, style: theme.textTheme.bodyMedium - ?.copyWith(color: theme.colorScheme.onBackground), + ?.copyWith(color: theme.colorScheme.onSurface), ), ), if (_foodProducer) ...[ @@ -274,24 +274,24 @@ class _SignUpPageState extends State with TraceableClientMixin { child: Checkbox( value: _subscribe, fillColor: - MaterialStateProperty.resolveWith(getCheckBoxColor), + WidgetStateProperty.resolveWith(getCheckBoxColor), onChanged: (_) {}, ), ), title: Text( appLocalizations.sign_up_page_subscribe_checkbox, style: theme.textTheme.bodyMedium - ?.copyWith(color: theme.colorScheme.onBackground), + ?.copyWith(color: theme.colorScheme.onSurface), ), ), const SizedBox(height: space), ElevatedButton( onPressed: () async => _signUp(), style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -447,7 +447,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { final bool agree; final bool disagree; - final MaterialPropertyResolver checkboxColorResolver; + final WidgetPropertyResolver checkboxColorResolver; final ValueChanged onCheckboxChanged; @override @@ -470,7 +470,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { ignoring: true, child: Checkbox( value: agree, - fillColor: MaterialStateProperty.resolveWith( + fillColor: WidgetStateProperty.resolveWith( checkboxColorResolver, ), onChanged: (_) {}, @@ -485,7 +485,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { // additional space needed because of the next text span text: '${appLocalizations.sign_up_page_agree_text} ', style: theme.textTheme.bodyMedium?.copyWith( - color: theme.colorScheme.onBackground, + color: theme.colorScheme.onSurface, ), ), TextSpan( @@ -509,7 +509,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { semanticLabel: appLocalizations.termsOfUse, Icons.info, color: checkboxColorResolver( - {MaterialState.selected}, + {WidgetState.selected}, ), ), ), diff --git a/packages/smooth_app/lib/smooth_category_picker_example.dart b/packages/smooth_app/lib/smooth_category_picker_example.dart index 48287c35432..86263096ff9 100644 --- a/packages/smooth_app/lib/smooth_category_picker_example.dart +++ b/packages/smooth_app/lib/smooth_category_picker_example.dart @@ -167,9 +167,8 @@ class _ExampleAppState extends State { foregroundColor: Colors.black, ), checkboxTheme: CheckboxTheme.of(context).copyWith( - fillColor: - MaterialStateColor.resolveWith((Set states) { - if (states.contains(MaterialState.selected)) { + fillColor: WidgetStateColor.resolveWith((Set states) { + if (states.contains(WidgetState.selected)) { return Colors.green; } return Colors.black38; diff --git a/packages/smooth_app/lib/themes/color_schemes.dart b/packages/smooth_app/lib/themes/color_schemes.dart index 9e31f3135f9..59bd71c4963 100644 --- a/packages/smooth_app/lib/themes/color_schemes.dart +++ b/packages/smooth_app/lib/themes/color_schemes.dart @@ -12,10 +12,8 @@ const ColorScheme lightColorScheme = ColorScheme( onSecondary: Color(0xFF000000), error: Color(0xFFEB5757), onError: Color(0xFFFFFFFF), - background: Color(0xFFFFFFFF), - onBackground: Color(0xFF000000), - surface: Color(0xFF85746C), - onSurface: Color(0xFFFFFFFF), + surface: Color(0xFFFFFFFF), + onSurface: Color(0xFF000000), ); const ColorScheme darkColorScheme = ColorScheme( @@ -27,10 +25,8 @@ const ColorScheme darkColorScheme = ColorScheme( onSecondary: Color(0xFFFFFFFF), error: Color(0xFFEB5757), onError: Color(0xFFFFFFFF), - background: Color(0xFF201A17), - onBackground: Color(0xFFFFFFFF), - surface: Color(0xFFEDE0DB), - onSurface: Color(0xFF000000), + surface: Color(0xFF201A17), + onSurface: Color(0xFFFFFFFF), ); const ColorScheme trueDarkColorScheme = ColorScheme( @@ -42,10 +38,8 @@ const ColorScheme trueDarkColorScheme = ColorScheme( onSecondary: Color(0xFFE1E1E1), error: Color(0xFFEA2B2B), onError: Color(0xFFE1E1E1), - background: Color(0xFF000000), - onBackground: Color(0xFFE1E1E1), surface: Color(0xFF000000), - onSurface: Color(0xFFE1E1E1), + onSurface: Color(0xFFFFFFFF), ); const String CONTRAST_LOW = 'Low'; diff --git a/packages/smooth_app/lib/themes/smooth_theme.dart b/packages/smooth_app/lib/themes/smooth_theme.dart index 301342c3123..1d41a28ecbe 100644 --- a/packages/smooth_app/lib/themes/smooth_theme.dart +++ b/packages/smooth_app/lib/themes/smooth_theme.dart @@ -47,7 +47,7 @@ class SmoothTheme { ], colorScheme: myColorScheme, canvasColor: themeProvider.currentTheme == THEME_AMOLED - ? myColorScheme.background + ? myColorScheme.surface : null, bottomNavigationBarTheme: BottomNavigationBarThemeData( selectedIconTheme: const IconThemeData(size: 24.0), @@ -61,11 +61,10 @@ class SmoothTheme { ), elevatedButtonTheme: ElevatedButtonThemeData( style: ButtonStyle( - backgroundColor: MaterialStateProperty.resolveWith( - (Set states) => - states.contains(MaterialState.disabled) - ? Colors.grey - : myColorScheme.primary, + backgroundColor: WidgetStateProperty.resolveWith( + (Set states) => states.contains(WidgetState.disabled) + ? Colors.grey + : myColorScheme.primary, ), ), ), @@ -76,8 +75,8 @@ class SmoothTheme { ? getTextTheme(themeProvider, textContrastProvider) : _TEXT_THEME, appBarTheme: AppBarTheme( - color: myColorScheme.background, - foregroundColor: myColorScheme.onBackground, + color: myColorScheme.surface, + foregroundColor: myColorScheme.onSurface, systemOverlayStyle: SystemUiOverlayStyle.light, ), dividerColor: const Color(0xFFdfdfdf), @@ -85,59 +84,59 @@ class SmoothTheme { fillColor: myColorScheme.secondary, ), iconTheme: IconThemeData( - color: myColorScheme.onBackground, + color: myColorScheme.onSurface, ), snackBarTheme: SnackBarThemeData( contentTextStyle: _TEXT_THEME.bodyMedium?.copyWith(color: myColorScheme.onPrimary), actionTextColor: myColorScheme.onPrimary, - backgroundColor: myColorScheme.onBackground, + backgroundColor: myColorScheme.onSurface, ), bannerTheme: MaterialBannerThemeData( contentTextStyle: TextStyle(color: myColorScheme.onSecondary), backgroundColor: myColorScheme.secondary, ), checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; }), ), radioTheme: RadioThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; }), ), switchTheme: SwitchThemeData( - thumbColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + thumbColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; }), - trackColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + trackColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; diff --git a/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart b/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart index c079a64c370..7a2de39e52a 100644 --- a/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart +++ b/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart @@ -29,7 +29,7 @@ class RankingFloatingActionButton extends StatelessWidget { child: ElevatedButton.icon( onPressed: onPressed, style: ButtonStyle( - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index eaec5236455..88fb418e666 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -903,10 +903,10 @@ packages: dependency: transitive description: name: in_app_review - sha256: "6cb7a8e4a2eecfa5868b35e1e9ac9082341eeead2cefaac8282be514736e9715" + sha256: "99869244d09adc76af16bf8fd731dd13cef58ecafd5917847589c49f378cbb30" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.9" in_app_review_platform_interface: dependency: transitive description: @@ -924,10 +924,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.19.0" iso_countries: dependency: "direct main" description: @@ -964,26 +964,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -1052,10 +1052,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" mgrs_dart: dependency: transitive description: @@ -1599,10 +1599,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" typed_data: dependency: transitive description: @@ -1743,10 +1743,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" watcher: dependency: transitive description: @@ -1852,5 +1852,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.3 <4.0.0" + dart: ">=3.4.0 <4.0.0" flutter: ">=3.19.0" diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index c0f7b8ff438..113f6f7bf8d 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.0+734 publish_to: "none" environment: - sdk: '>=3.3.3 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: @@ -54,7 +54,7 @@ dependencies: auto_size_text: 3.0.0 crop_image: 1.0.13 shared_preferences: 2.2.3 - intl: 0.18.1 + intl: 0.19.0 collection: 1.18.0 path: 1.9.0 path_provider: 2.1.3 From 1a9091c09d0ad4addf46e85b90bc9075749ce153 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 4 Jul 2024 10:33:23 +0200 Subject: [PATCH 55/85] chore: Revert Flutter bump to 3.22 (#5463) This reverts commit 9e211ca29c5caf33c5ca7401ab92235ccb81cb27. --- README.md | 2 +- flutter-version.txt | 2 +- .../app_store/apple_app_store/pubspec.yaml | 2 +- packages/app_store/google_play/pubspec.yaml | 2 +- packages/app_store/shared/pubspec.yaml | 2 +- packages/app_store/uri_store/pubspec.yaml | 2 +- packages/scanner/ml_kit/pubspec.yaml | 2 +- packages/scanner/shared/pubspec.yaml | 2 +- packages/scanner/zxing/pubspec.yaml | 2 +- .../buttons/smooth_simple_button.dart | 10 ++-- .../dialogs/smooth_alert_dialog.dart | 2 +- .../question_answers_options.dart | 4 +- .../smooth_app/lib/pages/image_crop_page.dart | 6 +-- .../pages/locations/location_query_page.dart | 4 +- .../onboarding/onboarding_bottom_bar.dart | 7 +-- .../v2/onboarding_bottom_hills.dart | 16 +++--- .../preferences/user_preferences_account.dart | 4 +- .../preferences/user_preferences_connect.dart | 2 +- .../preferences/user_preferences_rate_us.dart | 4 +- .../user_preferences_share_with_friends.dart | 4 +- .../product/common/product_list_page.dart | 2 +- .../lib/pages/product/edit_image_button.dart | 8 +-- .../pages/product/edit_new_packagings.dart | 2 +- .../pages/product/edit_ocr/edit_ocr_page.dart | 2 +- .../lib/pages/product/new_product_page.dart | 4 +- .../nutrition_add_nutrient_button.dart | 2 +- .../pages/product/nutrition_page_loaded.dart | 2 +- .../product/product_incomplete_card.dart | 6 +-- .../product_question_answers_options.dart | 2 +- .../lib/pages/scan/scan_header.dart | 2 +- .../smooth_app/lib/pages/scan/scan_page.dart | 2 +- .../lib/pages/scan/search_history_view.dart | 4 +- .../user_management/forgot_password_page.dart | 5 +- .../lib/pages/user_management/login_page.dart | 18 +++---- .../pages/user_management/sign_up_page.dart | 30 +++++------ .../lib/smooth_category_picker_example.dart | 5 +- .../smooth_app/lib/themes/color_schemes.dart | 16 ++++-- .../smooth_app/lib/themes/smooth_theme.dart | 51 ++++++++++--------- .../ranking_floating_action_button.dart | 2 +- packages/smooth_app/pubspec.lock | 34 ++++++------- packages/smooth_app/pubspec.yaml | 4 +- 41 files changed, 147 insertions(+), 137 deletions(-) diff --git a/README.md b/README.md index d8a99c424d2..1a81ca581a6 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ - Make sure you have installed flutter and all the requirements - [Official flutter installation guide](https://docs.flutter.dev/get-started/install) -- Currently, the app uses the following version of Flutter (3.22.x). +- Currently, the app uses the latest stable version of Flutter (3.19.x). We have predefined run configurations for Android Studio and Visual Studio Code diff --git a/flutter-version.txt b/flutter-version.txt index dbc9520ba41..0bc8e967b83 100644 --- a/flutter-version.txt +++ b/flutter-version.txt @@ -1 +1 @@ -3.22.2 \ No newline at end of file +3.19.5 \ No newline at end of file diff --git a/packages/app_store/apple_app_store/pubspec.yaml b/packages/app_store/apple_app_store/pubspec.yaml index 0a6b0494448..ed12d33a943 100644 --- a/packages/app_store/apple_app_store/pubspec.yaml +++ b/packages/app_store/apple_app_store/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/google_play/pubspec.yaml b/packages/app_store/google_play/pubspec.yaml index 54161b2443e..9f6c287d4fa 100644 --- a/packages/app_store/google_play/pubspec.yaml +++ b/packages/app_store/google_play/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/shared/pubspec.yaml b/packages/app_store/shared/pubspec.yaml index 86fec92bc7f..4978f448a6c 100644 --- a/packages/app_store/shared/pubspec.yaml +++ b/packages/app_store/shared/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/uri_store/pubspec.yaml b/packages/app_store/uri_store/pubspec.yaml index 1e661bdb92a..5b5d99659be 100644 --- a/packages/app_store/uri_store/pubspec.yaml +++ b/packages/app_store/uri_store/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/ml_kit/pubspec.yaml b/packages/scanner/ml_kit/pubspec.yaml index 753b8caafd2..5b69d47d97a 100644 --- a/packages/scanner/ml_kit/pubspec.yaml +++ b/packages/scanner/ml_kit/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/shared/pubspec.yaml b/packages/scanner/shared/pubspec.yaml index 7fa9a28d1f0..7730dc8abaf 100644 --- a/packages/scanner/shared/pubspec.yaml +++ b/packages/scanner/shared/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/zxing/pubspec.yaml b/packages/scanner/zxing/pubspec.yaml index 0e32939a7b4..76b0988cd50 100644 --- a/packages/scanner/zxing/pubspec.yaml +++ b/packages/scanner/zxing/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' dependencies: flutter: diff --git a/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart b/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart index 52dae9e156d..cc978a528ab 100644 --- a/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart +++ b/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart @@ -33,19 +33,19 @@ class SmoothSimpleButton extends StatelessWidget { style: ButtonStyle( backgroundColor: buttonColor == null ? null - : WidgetStateProperty.all(buttonColor!), - shape: WidgetStateProperty.all( + : MaterialStateProperty.all(buttonColor!), + shape: MaterialStateProperty.all( RoundedRectangleBorder(borderRadius: borderRadius), ), overlayColor: context.read().isAmoledTheme - ? WidgetStateProperty.resolveWith((Set states) { - return states.contains(WidgetState.pressed) + ? MaterialStateProperty.resolveWith((Set states) { + return states.contains(MaterialState.pressed) ? Theme.of(context).colorScheme.primary.withOpacity(0.3) : null; }) : null, side: context.read().isAmoledTheme - ? WidgetStateProperty.all( + ? MaterialStateProperty.all( const BorderSide(color: Colors.white), ) : null, diff --git a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart index 0d03fca3a89..f267cc1dba6 100644 --- a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart +++ b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart @@ -213,7 +213,7 @@ class _SmoothDialogTitle extends StatelessWidget { ], ), ), - Divider(color: Theme.of(context).colorScheme.onSurface), + Divider(color: Theme.of(context).colorScheme.onBackground), const SizedBox(height: 12), ], ); diff --git a/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart b/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart index e1ee8172f20..dcea8df0085 100755 --- a/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart +++ b/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart @@ -108,8 +108,8 @@ class QuestionAnswersOptions extends StatelessWidget { child: TextButton.icon( onPressed: () => onAnswer(insightAnnotation), style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(backgroundColor), - shape: WidgetStateProperty.all( + backgroundColor: MaterialStateProperty.all(backgroundColor), + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/image_crop_page.dart b/packages/smooth_app/lib/pages/image_crop_page.dart index 67f902807c1..614b7431c0a 100644 --- a/packages/smooth_app/lib/pages/image_crop_page.dart +++ b/packages/smooth_app/lib/pages/image_crop_page.dart @@ -225,13 +225,13 @@ class _ImageSourceButton extends StatelessWidget { child: OutlinedButton( onPressed: onPressed, style: ButtonStyle( - side: WidgetStatePropertyAll( + side: MaterialStatePropertyAll( BorderSide(color: primaryColor), ), - padding: const WidgetStatePropertyAll( + padding: const MaterialStatePropertyAll( EdgeInsets.symmetric(vertical: LARGE_SPACE), ), - shape: WidgetStatePropertyAll( + shape: MaterialStatePropertyAll( RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, side: BorderSide(color: primaryColor), diff --git a/packages/smooth_app/lib/pages/locations/location_query_page.dart b/packages/smooth_app/lib/pages/locations/location_query_page.dart index 61524e27a5e..250f35e0172 100644 --- a/packages/smooth_app/lib/pages/locations/location_query_page.dart +++ b/packages/smooth_app/lib/pages/locations/location_query_page.dart @@ -110,8 +110,8 @@ class _LocationQueryPageState extends State data: ListTileThemeData( titleTextStyle: const TextStyle(fontSize: 20.0), minLeadingWidth: 18.0, - iconColor: Theme.of(context).colorScheme.onSurface, - textColor: Theme.of(context).colorScheme.onSurface, + iconColor: Theme.of(context).colorScheme.onBackground, + textColor: Theme.of(context).colorScheme.onBackground, ), child: ListView.builder( itemBuilder: (BuildContext context, int index) => diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart index 089aed5f5ef..57e9b0abf83 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart @@ -90,11 +90,12 @@ class OnboardingBottomButton extends StatelessWidget { key: nextKey, onPressed: onPressed, style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(backgroundColor), + backgroundColor: MaterialStateProperty.all(backgroundColor), overlayColor: backgroundColor == Colors.white - ? WidgetStateProperty.all(Theme.of(context).splashColor) + ? MaterialStateProperty.all( + Theme.of(context).splashColor) : null, - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(40))), ), diff --git a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart index e8ecaa7c70b..49b3b784299 100644 --- a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart +++ b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart @@ -62,10 +62,10 @@ class OnboardingBottomHills extends StatelessWidget { end: 15.0, child: TextButton( style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( + backgroundColor: MaterialStateProperty.all( Colors.white, ), - padding: WidgetStateProperty.all( + padding: MaterialStateProperty.all( const EdgeInsetsDirectional.only( start: LARGE_SPACE + 1.0, end: LARGE_SPACE, @@ -73,20 +73,20 @@ class OnboardingBottomHills extends StatelessWidget { bottom: SMALL_SPACE, ), ), - elevation: WidgetStateProperty.all(4.0), - iconColor: WidgetStateProperty.all( + elevation: MaterialStateProperty.all(4.0), + iconColor: MaterialStateProperty.all( colors.orange, ), - foregroundColor: WidgetStateProperty.all( + foregroundColor: MaterialStateProperty.all( colors.orange, ), - iconSize: WidgetStateProperty.all(21.0), - shape: WidgetStateProperty.all( + iconSize: MaterialStateProperty.all(21.0), + shape: MaterialStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), ), ), - shadowColor: WidgetStateProperty.all( + shadowColor: MaterialStateProperty.all( Colors.black.withOpacity(0.50), ), ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart index 3121ddff96c..94ad1b57cb3 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart @@ -147,10 +147,10 @@ class UserPreferencesAccount extends AbstractUserPreferences { child: ElevatedButton( onPressed: () async => _goToLoginPage(), style: ButtonStyle( - minimumSize: WidgetStateProperty.all( + minimumSize: MaterialStateProperty.all( Size(size.width * 0.5, themeData.buttonTheme.height + 10), ), - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart index 1e4e0f169f5..8704baf50fa 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart @@ -111,7 +111,7 @@ class UserPreferencesConnect extends AbstractUserPreferences { 'assets/preferences/x-logo.svg', width: DEFAULT_ICON_SIZE, colorFilter: ui.ColorFilter.mode( - Theme.of(context).colorScheme.onSurface, + Theme.of(context).colorScheme.onBackground, ui.BlendMode.srcIn, ), package: AppHelper.APP_PACKAGE, diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart index 3600c1330ab..cba7fc5eefe 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart @@ -50,10 +50,10 @@ class UserPreferencesRateUs extends StatelessWidget { content: Text( appLocalizations.error_occurred, textAlign: TextAlign.center, - style: TextStyle(color: themeData.colorScheme.surface), + style: TextStyle(color: themeData.colorScheme.background), ), behavior: SnackBarBehavior.floating, - backgroundColor: themeData.colorScheme.onSurface, + backgroundColor: themeData.colorScheme.onBackground, ), ); } diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart index 44840fa1c28..6e9875ff5c3 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart @@ -44,11 +44,11 @@ class UserPreferencesShareWithFriends extends StatelessWidget { appLocalizations.error, textAlign: TextAlign.center, style: TextStyle( - color: themeData.colorScheme.surface, + color: themeData.colorScheme.background, ), ), behavior: SnackBarBehavior.floating, - backgroundColor: themeData.colorScheme.onSurface, + backgroundColor: themeData.colorScheme.onBackground, ), ); } diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index 59d9b4e671a..d831b6c70bc 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -267,7 +267,7 @@ class _ProductListPageState extends State appLocalizations.product_list_empty_message, textAlign: TextAlign.center, style: themeData.textTheme.bodyMedium?.apply( - color: themeData.colorScheme.onSurface, + color: themeData.colorScheme.onBackground, ), ), EMPTY_WIDGET, diff --git a/packages/smooth_app/lib/pages/product/edit_image_button.dart b/packages/smooth_app/lib/pages/product/edit_image_button.dart index dd30c53526f..bc644102552 100644 --- a/packages/smooth_app/lib/pages/product/edit_image_button.dart +++ b/packages/smooth_app/lib/pages/product/edit_image_button.dart @@ -33,20 +33,20 @@ class EditImageButton extends StatelessWidget { child: OutlinedButton.icon( icon: Icon(iconData), style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(colorScheme.onPrimary), - shape: WidgetStateProperty.all( + backgroundColor: MaterialStateProperty.all(colorScheme.onPrimary), + shape: MaterialStateProperty.all( const RoundedRectangleBorder(borderRadius: ROUNDED_BORDER_RADIUS), ), side: borderWidth == null ? null - : WidgetStateBorderSide.resolveWith( + : MaterialStateBorderSide.resolveWith( (_) => BorderSide( color: colorScheme.primary, width: borderWidth!, ), ), padding: _centerContent - ? WidgetStateProperty.all( + ? MaterialStateProperty.all( const EdgeInsets.symmetric( vertical: LARGE_SPACE, ), diff --git a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart index 4c0a003929b..6c4e248066c 100644 --- a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart +++ b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart @@ -324,7 +324,7 @@ Color _getSmoothCardColorAlternate(final BuildContext context, int index) { if (index.isOdd) { cardColor = PRIMARY_GREY_COLOR; } else { - cardColor = darkColorScheme.surface; + cardColor = darkColorScheme.background; } } diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index d78a52cce5e..1f737bc5744 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -294,7 +294,7 @@ class _EditOcrPageState extends State with UpToDateMixin { flex: 1, child: DecoratedBox( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, + color: Theme.of(context).colorScheme.background, borderRadius: const BorderRadiusDirectional.only( topStart: ANGULAR_RADIUS, topEnd: ANGULAR_RADIUS, diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index e20901edfa2..ee44bec4fb5 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -416,11 +416,11 @@ class _ProductPageState extends State ), child: ElevatedButton( style: ButtonStyle( - padding: WidgetStateProperty.all( + padding: MaterialStateProperty.all( const EdgeInsets.symmetric( horizontal: VERY_LARGE_SPACE, vertical: MEDIUM_SPACE), ), - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart b/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart index afa30d2b80d..86b1a5dea6a 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart @@ -99,7 +99,7 @@ class NutritionAddNutrientButton extends StatelessWidget { } }, style: ButtonStyle( - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, side: BorderSide.none, diff --git a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart index 6fed13681ec..3a872cbbf39 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart @@ -322,7 +322,7 @@ class _NutritionPageLoadedState extends State value: _nutritionContainer.noNutritionData, onChanged: (final bool value) => setState(() => _nutritionContainer.noNutritionData = value), - trackColor: WidgetStateProperty.all( + trackColor: MaterialStateProperty.all( Theme.of(context).colorScheme.onPrimary), ), ), diff --git a/packages/smooth_app/lib/pages/product/product_incomplete_card.dart b/packages/smooth_app/lib/pages/product/product_incomplete_card.dart index c60c7897639..ceba846b333 100644 --- a/packages/smooth_app/lib/pages/product/product_incomplete_card.dart +++ b/packages/smooth_app/lib/pages/product/product_incomplete_card.dart @@ -111,13 +111,13 @@ class ProductIncompleteCard extends StatelessWidget { ), ), style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( + backgroundColor: MaterialStateProperty.all( colorScheme.primary, ), - foregroundColor: WidgetStateProperty.all( + foregroundColor: MaterialStateProperty.all( colorScheme.onPrimary, ), - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder(borderRadius: ANGULAR_BORDER_RADIUS), ), ), diff --git a/packages/smooth_app/lib/pages/product/product_question_answers_options.dart b/packages/smooth_app/lib/pages/product/product_question_answers_options.dart index d9e1c31e72a..efeac877bd0 100644 --- a/packages/smooth_app/lib/pages/product/product_question_answers_options.dart +++ b/packages/smooth_app/lib/pages/product/product_question_answers_options.dart @@ -91,7 +91,7 @@ class ProductQuestionAnswersOptions extends StatelessWidget { child: TextButton( onPressed: () => onAnswer(insightAnnotation), style: ButtonStyle( - backgroundColor: WidgetStateProperty.all(backgroundColor), + backgroundColor: MaterialStateProperty.all(backgroundColor), ), child: Text( buttonText, diff --git a/packages/smooth_app/lib/pages/scan/scan_header.dart b/packages/smooth_app/lib/pages/scan/scan_header.dart index 53cbe5bbb6e..ab419653504 100644 --- a/packages/smooth_app/lib/pages/scan/scan_header.dart +++ b/packages/smooth_app/lib/pages/scan/scan_header.dart @@ -24,7 +24,7 @@ class _ScanHeaderState extends State { final ContinuousScanModel model = context.watch(); final ButtonStyle buttonStyle = ButtonStyle( - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(18.0)), ), diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index 26f22f14e30..f1a4f4401ea 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -64,7 +64,7 @@ class _ScanPageState extends State { color: Colors.white, child: SafeArea( child: Container( - color: Theme.of(context).colorScheme.surface, + color: Theme.of(context).colorScheme.background, child: Column( children: [ if (hasACamera) diff --git a/packages/smooth_app/lib/pages/scan/search_history_view.dart b/packages/smooth_app/lib/pages/scan/search_history_view.dart index a4b0a94507a..975da30935f 100644 --- a/packages/smooth_app/lib/pages/scan/search_history_view.dart +++ b/packages/smooth_app/lib/pages/scan/search_history_view.dart @@ -46,8 +46,8 @@ class _SearchHistoryViewState extends State { data: ListTileThemeData( titleTextStyle: const TextStyle(fontSize: 20.0), minLeadingWidth: 18.0, - iconColor: Theme.of(context).colorScheme.onSurface, - textColor: Theme.of(context).colorScheme.onSurface, + iconColor: Theme.of(context).colorScheme.onBackground, + textColor: Theme.of(context).colorScheme.onBackground, ), child: ListView.builder( itemBuilder: (BuildContext context, int i) { diff --git a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart index 42108e73d1e..028ad5d5f38 100644 --- a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart +++ b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart @@ -150,10 +150,11 @@ class _ForgotPasswordPageState extends State } }, style: ButtonStyle( - minimumSize: WidgetStateProperty.all( + minimumSize: MaterialStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: WidgetStateProperty.all( + shape: + MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/user_management/login_page.dart b/packages/smooth_app/lib/pages/user_management/login_page.dart index cbda47ad48b..fbd7e963e49 100644 --- a/packages/smooth_app/lib/pages/user_management/login_page.dart +++ b/packages/smooth_app/lib/pages/user_management/login_page.dart @@ -221,12 +221,12 @@ class _LoginPageState extends State with TraceableClientMixin { ElevatedButton( onPressed: () => _login(context), style: ButtonStyle( - minimumSize: WidgetStateProperty.all( + minimumSize: MaterialStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: - WidgetStateProperty.all( + shape: MaterialStateProperty.all< + RoundedRectangleBorder>( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -249,14 +249,14 @@ class _LoginPageState extends State with TraceableClientMixin { //Forgot password TextButton( style: ButtonStyle( - padding: WidgetStateProperty.all( + padding: MaterialStateProperty.all( const EdgeInsets.symmetric( vertical: 10.0, horizontal: VERY_LARGE_SPACE, ), ), shape: - WidgetStateProperty.all( + MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -304,15 +304,15 @@ class _LoginPageState extends State with TraceableClientMixin { } }, style: ButtonStyle( - side: WidgetStateProperty.all( + side: MaterialStateProperty.all( BorderSide( color: theme.colorScheme.primary, width: 2.0), ), - minimumSize: WidgetStateProperty.all( + minimumSize: MaterialStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height), ), - shape: - WidgetStateProperty.all( + shape: MaterialStateProperty.all< + RoundedRectangleBorder>( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart index 8bbd6b10238..48f2713516f 100644 --- a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart +++ b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart @@ -56,11 +56,11 @@ class _SignUpPageState extends State with TraceableClientMixin { final AppLocalizations appLocalizations = AppLocalizations.of(context); final Size size = MediaQuery.sizeOf(context); - Color getCheckBoxColor(Set states) { - const Set interactiveStates = { - WidgetState.pressed, - WidgetState.hovered, - WidgetState.focused, + Color getCheckBoxColor(Set states) { + const Set interactiveStates = { + MaterialState.pressed, + MaterialState.hovered, + MaterialState.focused, }; if (states.any(interactiveStates.contains)) { return theme.colorScheme.onSurface; @@ -236,14 +236,14 @@ class _SignUpPageState extends State with TraceableClientMixin { child: Checkbox( value: _foodProducer, fillColor: - WidgetStateProperty.resolveWith(getCheckBoxColor), + MaterialStateProperty.resolveWith(getCheckBoxColor), onChanged: (_) {}, ), ), title: Text( appLocalizations.sign_up_page_producer_checkbox, style: theme.textTheme.bodyMedium - ?.copyWith(color: theme.colorScheme.onSurface), + ?.copyWith(color: theme.colorScheme.onBackground), ), ), if (_foodProducer) ...[ @@ -274,24 +274,24 @@ class _SignUpPageState extends State with TraceableClientMixin { child: Checkbox( value: _subscribe, fillColor: - WidgetStateProperty.resolveWith(getCheckBoxColor), + MaterialStateProperty.resolveWith(getCheckBoxColor), onChanged: (_) {}, ), ), title: Text( appLocalizations.sign_up_page_subscribe_checkbox, style: theme.textTheme.bodyMedium - ?.copyWith(color: theme.colorScheme.onSurface), + ?.copyWith(color: theme.colorScheme.onBackground), ), ), const SizedBox(height: space), ElevatedButton( onPressed: () async => _signUp(), style: ButtonStyle( - minimumSize: WidgetStateProperty.all( + minimumSize: MaterialStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -447,7 +447,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { final bool agree; final bool disagree; - final WidgetPropertyResolver checkboxColorResolver; + final MaterialPropertyResolver checkboxColorResolver; final ValueChanged onCheckboxChanged; @override @@ -470,7 +470,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { ignoring: true, child: Checkbox( value: agree, - fillColor: WidgetStateProperty.resolveWith( + fillColor: MaterialStateProperty.resolveWith( checkboxColorResolver, ), onChanged: (_) {}, @@ -485,7 +485,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { // additional space needed because of the next text span text: '${appLocalizations.sign_up_page_agree_text} ', style: theme.textTheme.bodyMedium?.copyWith( - color: theme.colorScheme.onSurface, + color: theme.colorScheme.onBackground, ), ), TextSpan( @@ -509,7 +509,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { semanticLabel: appLocalizations.termsOfUse, Icons.info, color: checkboxColorResolver( - {WidgetState.selected}, + {MaterialState.selected}, ), ), ), diff --git a/packages/smooth_app/lib/smooth_category_picker_example.dart b/packages/smooth_app/lib/smooth_category_picker_example.dart index 86263096ff9..48287c35432 100644 --- a/packages/smooth_app/lib/smooth_category_picker_example.dart +++ b/packages/smooth_app/lib/smooth_category_picker_example.dart @@ -167,8 +167,9 @@ class _ExampleAppState extends State { foregroundColor: Colors.black, ), checkboxTheme: CheckboxTheme.of(context).copyWith( - fillColor: WidgetStateColor.resolveWith((Set states) { - if (states.contains(WidgetState.selected)) { + fillColor: + MaterialStateColor.resolveWith((Set states) { + if (states.contains(MaterialState.selected)) { return Colors.green; } return Colors.black38; diff --git a/packages/smooth_app/lib/themes/color_schemes.dart b/packages/smooth_app/lib/themes/color_schemes.dart index 59bd71c4963..9e31f3135f9 100644 --- a/packages/smooth_app/lib/themes/color_schemes.dart +++ b/packages/smooth_app/lib/themes/color_schemes.dart @@ -12,8 +12,10 @@ const ColorScheme lightColorScheme = ColorScheme( onSecondary: Color(0xFF000000), error: Color(0xFFEB5757), onError: Color(0xFFFFFFFF), - surface: Color(0xFFFFFFFF), - onSurface: Color(0xFF000000), + background: Color(0xFFFFFFFF), + onBackground: Color(0xFF000000), + surface: Color(0xFF85746C), + onSurface: Color(0xFFFFFFFF), ); const ColorScheme darkColorScheme = ColorScheme( @@ -25,8 +27,10 @@ const ColorScheme darkColorScheme = ColorScheme( onSecondary: Color(0xFFFFFFFF), error: Color(0xFFEB5757), onError: Color(0xFFFFFFFF), - surface: Color(0xFF201A17), - onSurface: Color(0xFFFFFFFF), + background: Color(0xFF201A17), + onBackground: Color(0xFFFFFFFF), + surface: Color(0xFFEDE0DB), + onSurface: Color(0xFF000000), ); const ColorScheme trueDarkColorScheme = ColorScheme( @@ -38,8 +42,10 @@ const ColorScheme trueDarkColorScheme = ColorScheme( onSecondary: Color(0xFFE1E1E1), error: Color(0xFFEA2B2B), onError: Color(0xFFE1E1E1), + background: Color(0xFF000000), + onBackground: Color(0xFFE1E1E1), surface: Color(0xFF000000), - onSurface: Color(0xFFFFFFFF), + onSurface: Color(0xFFE1E1E1), ); const String CONTRAST_LOW = 'Low'; diff --git a/packages/smooth_app/lib/themes/smooth_theme.dart b/packages/smooth_app/lib/themes/smooth_theme.dart index 1d41a28ecbe..301342c3123 100644 --- a/packages/smooth_app/lib/themes/smooth_theme.dart +++ b/packages/smooth_app/lib/themes/smooth_theme.dart @@ -47,7 +47,7 @@ class SmoothTheme { ], colorScheme: myColorScheme, canvasColor: themeProvider.currentTheme == THEME_AMOLED - ? myColorScheme.surface + ? myColorScheme.background : null, bottomNavigationBarTheme: BottomNavigationBarThemeData( selectedIconTheme: const IconThemeData(size: 24.0), @@ -61,10 +61,11 @@ class SmoothTheme { ), elevatedButtonTheme: ElevatedButtonThemeData( style: ButtonStyle( - backgroundColor: WidgetStateProperty.resolveWith( - (Set states) => states.contains(WidgetState.disabled) - ? Colors.grey - : myColorScheme.primary, + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) => + states.contains(MaterialState.disabled) + ? Colors.grey + : myColorScheme.primary, ), ), ), @@ -75,8 +76,8 @@ class SmoothTheme { ? getTextTheme(themeProvider, textContrastProvider) : _TEXT_THEME, appBarTheme: AppBarTheme( - color: myColorScheme.surface, - foregroundColor: myColorScheme.onSurface, + color: myColorScheme.background, + foregroundColor: myColorScheme.onBackground, systemOverlayStyle: SystemUiOverlayStyle.light, ), dividerColor: const Color(0xFFdfdfdf), @@ -84,59 +85,59 @@ class SmoothTheme { fillColor: myColorScheme.secondary, ), iconTheme: IconThemeData( - color: myColorScheme.onSurface, + color: myColorScheme.onBackground, ), snackBarTheme: SnackBarThemeData( contentTextStyle: _TEXT_THEME.bodyMedium?.copyWith(color: myColorScheme.onPrimary), actionTextColor: myColorScheme.onPrimary, - backgroundColor: myColorScheme.onSurface, + backgroundColor: myColorScheme.onBackground, ), bannerTheme: MaterialBannerThemeData( contentTextStyle: TextStyle(color: myColorScheme.onSecondary), backgroundColor: myColorScheme.secondary, ), checkboxTheme: CheckboxThemeData( - fillColor: - WidgetStateProperty.resolveWith((Set states) { - if (states.contains(WidgetState.disabled)) { + fillColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.disabled)) { return null; } - if (states.contains(WidgetState.selected)) { + if (states.contains(MaterialState.selected)) { return myColorScheme.primary; } return null; }), ), radioTheme: RadioThemeData( - fillColor: - WidgetStateProperty.resolveWith((Set states) { - if (states.contains(WidgetState.disabled)) { + fillColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.disabled)) { return null; } - if (states.contains(WidgetState.selected)) { + if (states.contains(MaterialState.selected)) { return myColorScheme.primary; } return null; }), ), switchTheme: SwitchThemeData( - thumbColor: - WidgetStateProperty.resolveWith((Set states) { - if (states.contains(WidgetState.disabled)) { + thumbColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.disabled)) { return null; } - if (states.contains(WidgetState.selected)) { + if (states.contains(MaterialState.selected)) { return myColorScheme.primary; } return null; }), - trackColor: - WidgetStateProperty.resolveWith((Set states) { - if (states.contains(WidgetState.disabled)) { + trackColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.disabled)) { return null; } - if (states.contains(WidgetState.selected)) { + if (states.contains(MaterialState.selected)) { return myColorScheme.primary; } return null; diff --git a/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart b/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart index 7a2de39e52a..c079a64c370 100644 --- a/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart +++ b/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart @@ -29,7 +29,7 @@ class RankingFloatingActionButton extends StatelessWidget { child: ElevatedButton.icon( onPressed: onPressed, style: ButtonStyle( - shape: WidgetStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 88fb418e666..eaec5236455 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -903,10 +903,10 @@ packages: dependency: transitive description: name: in_app_review - sha256: "99869244d09adc76af16bf8fd731dd13cef58ecafd5917847589c49f378cbb30" + sha256: "6cb7a8e4a2eecfa5868b35e1e9ac9082341eeead2cefaac8282be514736e9715" url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.0.4" in_app_review_platform_interface: dependency: transitive description: @@ -924,10 +924,10 @@ packages: dependency: "direct main" description: name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.19.0" + version: "0.18.1" iso_countries: dependency: "direct main" description: @@ -964,26 +964,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.0" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "2.0.1" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "2.0.1" lints: dependency: transitive description: @@ -1052,10 +1052,10 @@ packages: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.11.0" mgrs_dart: dependency: transitive description: @@ -1599,10 +1599,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -1743,10 +1743,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "13.0.0" watcher: dependency: transitive description: @@ -1852,5 +1852,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.3.3 <4.0.0" flutter: ">=3.19.0" diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 113f6f7bf8d..c0f7b8ff438 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.0+734 publish_to: "none" environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '>=3.3.3 <4.0.0' dependencies: flutter: @@ -54,7 +54,7 @@ dependencies: auto_size_text: 3.0.0 crop_image: 1.0.13 shared_preferences: 2.2.3 - intl: 0.19.0 + intl: 0.18.1 collection: 1.18.0 path: 1.9.0 path_provider: 2.1.3 From b1950ac65fd748d7bf532d8627e04baa4f4b3245 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 4 Jul 2024 10:49:49 +0200 Subject: [PATCH 56/85] Bump mobile_scanner to fix a crash on iOS (#5464) --- packages/scanner/ml_kit/pubspec.yaml | 2 +- packages/smooth_app/ios/Podfile.lock | 8 ++--- packages/smooth_app/pubspec.lock | 48 ++++++++++++++-------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/scanner/ml_kit/pubspec.yaml b/packages/scanner/ml_kit/pubspec.yaml index 5b69d47d97a..5943857e06a 100644 --- a/packages/scanner/ml_kit/pubspec.yaml +++ b/packages/scanner/ml_kit/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: visibility_detector: 0.4.0+2 async: 2.11.0 - mobile_scanner: 3.5.2 + mobile_scanner: 4.0.1 scanner_shared: path: ../shared diff --git a/packages/smooth_app/ios/Podfile.lock b/packages/smooth_app/ios/Podfile.lock index 2f5b56c434c..04989447e33 100644 --- a/packages/smooth_app/ios/Podfile.lock +++ b/packages/smooth_app/ios/Podfile.lock @@ -101,7 +101,7 @@ PODS: - GTMSessionFetcher/Core (< 3.0, >= 1.1) - MLImage (= 1.0.0-beta4) - MLKitCommon (~> 9.0) - - mobile_scanner (3.5.2): + - mobile_scanner (3.5.6): - Flutter - GoogleMLKit/BarcodeScanning (~> 4.0.0) - MTBBarcodeScanner (5.0.11) @@ -268,7 +268,7 @@ SPEC CHECKSUMS: connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_custom_tabs_ios: 62439c843b2691aae516fd50119a01eb9755fff7 + flutter_custom_tabs_ios: a651b18786388923b62de8c0537607de87c2eccf flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40 flutter_icmp_ping: 2b159955eee0c487c766ad83fec224ae35e7c935 flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e @@ -281,7 +281,7 @@ SPEC CHECKSUMS: GoogleUtilitiesComponents: 679b2c881db3b615a2777504623df6122dd20afe GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 - in_app_review: 4a97249f7a2f539a0f294c2d9196b7fe35e49541 + in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d integration_test: 13825b8a9334a850581300559b8839134b124670 iso_countries: eb09d40f388e4c65e291e0bb36a701dfe7de6c74 libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 @@ -290,7 +290,7 @@ SPEC CHECKSUMS: MLKitBarcodeScanning: 04e264482c5f3810cb89ebc134ef6b61e67db505 MLKitCommon: c1b791c3e667091918d91bda4bba69a91011e390 MLKitVision: 8baa5f46ee3352614169b85250574fde38c36f49 - mobile_scanner: 5090a13b7a35fc1c25b0d97e18e84f271a6eb605 + mobile_scanner: 38dcd8a49d7d485f632b7de65e4900010187aef2 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb nanopb: 438bc412db1928dac798aa6fd75726007be04262 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index eaec5236455..d346af35141 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -65,10 +65,10 @@ packages: dependency: transitive description: name: archive - sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265 + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.6.1" args: dependency: transitive description: @@ -526,34 +526,34 @@ packages: dependency: transitive description: name: flutter_custom_tabs_android - sha256: "5701a3e38117dfc59e5fa9e84a29eea9203e0062de7be56d1f775845c34456d9" + sha256: cf06fde8c002f326dc6cbf69ee3f97c3feead4436229da02d2e2aa39d5a5dbf4 url: "https://pub.dev" source: hosted - version: "2.0.0+1" + version: "2.1.0" flutter_custom_tabs_ios: dependency: transitive description: name: flutter_custom_tabs_ios - sha256: b29f687f7f366159d37347f888369fcd1259adac8ca6c7f07d356a80b091e08a + sha256: ef2de533bc45fb84fefc3854bc8b1e43001671c6bc6bc55faa57942eecd3f70a url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" flutter_custom_tabs_platform_interface: dependency: transitive description: name: flutter_custom_tabs_platform_interface - sha256: "13531a743486695d87b462b151801e11476b1b5a15274caec092420cc1943064" + sha256: e18e9b08f92582123bdb84fb6e4c91804b0579700fed6f887d32fd9a1e96a5d5 url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" flutter_custom_tabs_web: dependency: transitive description: name: flutter_custom_tabs_web - sha256: "3114b511d3942ed42c502cc57ad47eaef9622ac06dd036e2b21b19d8876f6498" + sha256: "08ae322b11e1972a233d057542279873d0f9d1d5f8159c2c741457239d9d562c" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" flutter_driver: dependency: "direct dev" description: flutter @@ -688,10 +688,10 @@ packages: dependency: transitive description: name: flutter_secure_storage_macos - sha256: b768a7dab26d6186b68e2831b3104f8968154f0f4fdbf66e7c2dd7bdf299daaf + sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" flutter_secure_storage_platform_interface: dependency: transitive description: @@ -863,10 +863,10 @@ packages: dependency: transitive description: name: image_picker_ios - sha256: f3285238eb1474ee42946f557ad7df17aa6a2cf4106c2f41bdc948cd71c8b5e5 + sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447" url: "https://pub.dev" source: hosted - version: "0.8.11+1" + version: "0.8.12" image_picker_linux: dependency: transitive description: @@ -903,10 +903,10 @@ packages: dependency: transitive description: name: in_app_review - sha256: "6cb7a8e4a2eecfa5868b35e1e9ac9082341eeead2cefaac8282be514736e9715" + sha256: "99869244d09adc76af16bf8fd731dd13cef58ecafd5917847589c49f378cbb30" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.9" in_app_review_platform_interface: dependency: transitive description: @@ -1076,10 +1076,10 @@ packages: dependency: transitive description: name: mobile_scanner - sha256: cf978740676ba5b0c17399baf117984b31190bb7a6eaa43e51229ed46abc42ee + sha256: "827765afbd4792ff3fd105ad593821ac0f6d8a7d352689013b07ee85be336312" url: "https://pub.dev" source: hosted - version: "3.5.2" + version: "4.0.1" mockito: dependency: "direct dev" description: @@ -1221,18 +1221,18 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5" + sha256: b29a799ca03be9f999aa6c39f7de5209482d638e6f857f6b93b0875c618b7e54 url: "https://pub.dev" source: hosted - version: "12.0.6" + version: "12.0.7" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662 + sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0 url: "https://pub.dev" source: hosted - version: "9.4.4" + version: "9.4.5" permission_handler_html: dependency: transitive description: @@ -1639,10 +1639,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" + sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" url_launcher_ios: dependency: transitive description: From d2ac037b7447d53bcda0615fc3f19ca71a2af213 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 4 Jul 2024 15:28:58 +0200 Subject: [PATCH 57/85] Revert "chore: Revert Flutter bump to 3.22 (#5463)" (#5468) This reverts commit 1a9091c09d0ad4addf46e85b90bc9075749ce153. --- README.md | 2 +- flutter-version.txt | 2 +- .../app_store/apple_app_store/pubspec.yaml | 2 +- packages/app_store/google_play/pubspec.yaml | 2 +- packages/app_store/shared/pubspec.yaml | 2 +- packages/app_store/uri_store/pubspec.yaml | 2 +- packages/scanner/ml_kit/pubspec.yaml | 2 +- packages/scanner/shared/pubspec.yaml | 2 +- packages/scanner/zxing/pubspec.yaml | 2 +- .../buttons/smooth_simple_button.dart | 10 ++-- .../dialogs/smooth_alert_dialog.dart | 2 +- .../question_answers_options.dart | 4 +- .../smooth_app/lib/pages/image_crop_page.dart | 6 +-- .../pages/locations/location_query_page.dart | 4 +- .../onboarding/onboarding_bottom_bar.dart | 7 ++- .../v2/onboarding_bottom_hills.dart | 16 +++--- .../preferences/user_preferences_account.dart | 4 +- .../preferences/user_preferences_connect.dart | 2 +- .../preferences/user_preferences_rate_us.dart | 4 +- .../user_preferences_share_with_friends.dart | 4 +- .../product/common/product_list_page.dart | 2 +- .../lib/pages/product/edit_image_button.dart | 8 +-- .../pages/product/edit_new_packagings.dart | 2 +- .../pages/product/edit_ocr/edit_ocr_page.dart | 2 +- .../lib/pages/product/new_product_page.dart | 4 +- .../nutrition_add_nutrient_button.dart | 2 +- .../pages/product/nutrition_page_loaded.dart | 2 +- .../product/product_incomplete_card.dart | 6 +-- .../product_question_answers_options.dart | 2 +- .../lib/pages/scan/scan_header.dart | 2 +- .../smooth_app/lib/pages/scan/scan_page.dart | 2 +- .../lib/pages/scan/search_history_view.dart | 4 +- .../user_management/forgot_password_page.dart | 5 +- .../lib/pages/user_management/login_page.dart | 18 +++---- .../pages/user_management/sign_up_page.dart | 30 +++++------ .../lib/smooth_category_picker_example.dart | 5 +- .../smooth_app/lib/themes/color_schemes.dart | 16 ++---- .../smooth_app/lib/themes/smooth_theme.dart | 51 +++++++++---------- .../ranking_floating_action_button.dart | 2 +- packages/smooth_app/pubspec.lock | 30 +++++------ packages/smooth_app/pubspec.yaml | 4 +- 41 files changed, 135 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index 1a81ca581a6..d8a99c424d2 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ - Make sure you have installed flutter and all the requirements - [Official flutter installation guide](https://docs.flutter.dev/get-started/install) -- Currently, the app uses the latest stable version of Flutter (3.19.x). +- Currently, the app uses the following version of Flutter (3.22.x). We have predefined run configurations for Android Studio and Visual Studio Code diff --git a/flutter-version.txt b/flutter-version.txt index 0bc8e967b83..dbc9520ba41 100644 --- a/flutter-version.txt +++ b/flutter-version.txt @@ -1 +1 @@ -3.19.5 \ No newline at end of file +3.22.2 \ No newline at end of file diff --git a/packages/app_store/apple_app_store/pubspec.yaml b/packages/app_store/apple_app_store/pubspec.yaml index ed12d33a943..0a6b0494448 100644 --- a/packages/app_store/apple_app_store/pubspec.yaml +++ b/packages/app_store/apple_app_store/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/google_play/pubspec.yaml b/packages/app_store/google_play/pubspec.yaml index 9f6c287d4fa..54161b2443e 100644 --- a/packages/app_store/google_play/pubspec.yaml +++ b/packages/app_store/google_play/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/shared/pubspec.yaml b/packages/app_store/shared/pubspec.yaml index 4978f448a6c..86fec92bc7f 100644 --- a/packages/app_store/shared/pubspec.yaml +++ b/packages/app_store/shared/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/app_store/uri_store/pubspec.yaml b/packages/app_store/uri_store/pubspec.yaml index 5b5d99659be..1e661bdb92a 100644 --- a/packages/app_store/uri_store/pubspec.yaml +++ b/packages/app_store/uri_store/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.1 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/ml_kit/pubspec.yaml b/packages/scanner/ml_kit/pubspec.yaml index 5943857e06a..4dca15bc983 100644 --- a/packages/scanner/ml_kit/pubspec.yaml +++ b/packages/scanner/ml_kit/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/shared/pubspec.yaml b/packages/scanner/shared/pubspec.yaml index 7730dc8abaf..7fa9a28d1f0 100644 --- a/packages/scanner/shared/pubspec.yaml +++ b/packages/scanner/shared/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/scanner/zxing/pubspec.yaml b/packages/scanner/zxing/pubspec.yaml index 76b0988cd50..0e32939a7b4 100644 --- a/packages/scanner/zxing/pubspec.yaml +++ b/packages/scanner/zxing/pubspec.yaml @@ -4,7 +4,7 @@ version: 1.0.0 publish_to: "none" environment: - sdk: '>=3.3.0 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: diff --git a/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart b/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart index cc978a528ab..52dae9e156d 100644 --- a/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart +++ b/packages/smooth_app/lib/generic_lib/buttons/smooth_simple_button.dart @@ -33,19 +33,19 @@ class SmoothSimpleButton extends StatelessWidget { style: ButtonStyle( backgroundColor: buttonColor == null ? null - : MaterialStateProperty.all(buttonColor!), - shape: MaterialStateProperty.all( + : WidgetStateProperty.all(buttonColor!), + shape: WidgetStateProperty.all( RoundedRectangleBorder(borderRadius: borderRadius), ), overlayColor: context.read().isAmoledTheme - ? MaterialStateProperty.resolveWith((Set states) { - return states.contains(MaterialState.pressed) + ? WidgetStateProperty.resolveWith((Set states) { + return states.contains(WidgetState.pressed) ? Theme.of(context).colorScheme.primary.withOpacity(0.3) : null; }) : null, side: context.read().isAmoledTheme - ? MaterialStateProperty.all( + ? WidgetStateProperty.all( const BorderSide(color: Colors.white), ) : null, diff --git a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart index f267cc1dba6..0d03fca3a89 100644 --- a/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart +++ b/packages/smooth_app/lib/generic_lib/dialogs/smooth_alert_dialog.dart @@ -213,7 +213,7 @@ class _SmoothDialogTitle extends StatelessWidget { ], ), ), - Divider(color: Theme.of(context).colorScheme.onBackground), + Divider(color: Theme.of(context).colorScheme.onSurface), const SizedBox(height: 12), ], ); diff --git a/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart b/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart index dcea8df0085..e1ee8172f20 100755 --- a/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart +++ b/packages/smooth_app/lib/pages/hunger_games/question_answers_options.dart @@ -108,8 +108,8 @@ class QuestionAnswersOptions extends StatelessWidget { child: TextButton.icon( onPressed: () => onAnswer(insightAnnotation), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(backgroundColor), - shape: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all(backgroundColor), + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/image_crop_page.dart b/packages/smooth_app/lib/pages/image_crop_page.dart index 614b7431c0a..67f902807c1 100644 --- a/packages/smooth_app/lib/pages/image_crop_page.dart +++ b/packages/smooth_app/lib/pages/image_crop_page.dart @@ -225,13 +225,13 @@ class _ImageSourceButton extends StatelessWidget { child: OutlinedButton( onPressed: onPressed, style: ButtonStyle( - side: MaterialStatePropertyAll( + side: WidgetStatePropertyAll( BorderSide(color: primaryColor), ), - padding: const MaterialStatePropertyAll( + padding: const WidgetStatePropertyAll( EdgeInsets.symmetric(vertical: LARGE_SPACE), ), - shape: MaterialStatePropertyAll( + shape: WidgetStatePropertyAll( RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, side: BorderSide(color: primaryColor), diff --git a/packages/smooth_app/lib/pages/locations/location_query_page.dart b/packages/smooth_app/lib/pages/locations/location_query_page.dart index 250f35e0172..61524e27a5e 100644 --- a/packages/smooth_app/lib/pages/locations/location_query_page.dart +++ b/packages/smooth_app/lib/pages/locations/location_query_page.dart @@ -110,8 +110,8 @@ class _LocationQueryPageState extends State data: ListTileThemeData( titleTextStyle: const TextStyle(fontSize: 20.0), minLeadingWidth: 18.0, - iconColor: Theme.of(context).colorScheme.onBackground, - textColor: Theme.of(context).colorScheme.onBackground, + iconColor: Theme.of(context).colorScheme.onSurface, + textColor: Theme.of(context).colorScheme.onSurface, ), child: ListView.builder( itemBuilder: (BuildContext context, int index) => diff --git a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart index 57e9b0abf83..089aed5f5ef 100644 --- a/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart +++ b/packages/smooth_app/lib/pages/onboarding/onboarding_bottom_bar.dart @@ -90,12 +90,11 @@ class OnboardingBottomButton extends StatelessWidget { key: nextKey, onPressed: onPressed, style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(backgroundColor), + backgroundColor: WidgetStateProperty.all(backgroundColor), overlayColor: backgroundColor == Colors.white - ? MaterialStateProperty.all( - Theme.of(context).splashColor) + ? WidgetStateProperty.all(Theme.of(context).splashColor) : null, - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(40))), ), diff --git a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart index 49b3b784299..e8ecaa7c70b 100644 --- a/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart +++ b/packages/smooth_app/lib/pages/onboarding/v2/onboarding_bottom_hills.dart @@ -62,10 +62,10 @@ class OnboardingBottomHills extends StatelessWidget { end: 15.0, child: TextButton( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( Colors.white, ), - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsetsDirectional.only( start: LARGE_SPACE + 1.0, end: LARGE_SPACE, @@ -73,20 +73,20 @@ class OnboardingBottomHills extends StatelessWidget { bottom: SMALL_SPACE, ), ), - elevation: MaterialStateProperty.all(4.0), - iconColor: MaterialStateProperty.all( + elevation: WidgetStateProperty.all(4.0), + iconColor: WidgetStateProperty.all( colors.orange, ), - foregroundColor: MaterialStateProperty.all( + foregroundColor: WidgetStateProperty.all( colors.orange, ), - iconSize: MaterialStateProperty.all(21.0), - shape: MaterialStateProperty.all( + iconSize: WidgetStateProperty.all(21.0), + shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0), ), ), - shadowColor: MaterialStateProperty.all( + shadowColor: WidgetStateProperty.all( Colors.black.withOpacity(0.50), ), ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart index 94ad1b57cb3..3121ddff96c 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_account.dart @@ -147,10 +147,10 @@ class UserPreferencesAccount extends AbstractUserPreferences { child: ElevatedButton( onPressed: () async => _goToLoginPage(), style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, themeData.buttonTheme.height + 10), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart index 8704baf50fa..1e4e0f169f5 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart @@ -111,7 +111,7 @@ class UserPreferencesConnect extends AbstractUserPreferences { 'assets/preferences/x-logo.svg', width: DEFAULT_ICON_SIZE, colorFilter: ui.ColorFilter.mode( - Theme.of(context).colorScheme.onBackground, + Theme.of(context).colorScheme.onSurface, ui.BlendMode.srcIn, ), package: AppHelper.APP_PACKAGE, diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart index cba7fc5eefe..3600c1330ab 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_rate_us.dart @@ -50,10 +50,10 @@ class UserPreferencesRateUs extends StatelessWidget { content: Text( appLocalizations.error_occurred, textAlign: TextAlign.center, - style: TextStyle(color: themeData.colorScheme.background), + style: TextStyle(color: themeData.colorScheme.surface), ), behavior: SnackBarBehavior.floating, - backgroundColor: themeData.colorScheme.onBackground, + backgroundColor: themeData.colorScheme.onSurface, ), ); } diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart index 6e9875ff5c3..44840fa1c28 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_share_with_friends.dart @@ -44,11 +44,11 @@ class UserPreferencesShareWithFriends extends StatelessWidget { appLocalizations.error, textAlign: TextAlign.center, style: TextStyle( - color: themeData.colorScheme.background, + color: themeData.colorScheme.surface, ), ), behavior: SnackBarBehavior.floating, - backgroundColor: themeData.colorScheme.onBackground, + backgroundColor: themeData.colorScheme.onSurface, ), ); } diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index d831b6c70bc..59d9b4e671a 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -267,7 +267,7 @@ class _ProductListPageState extends State appLocalizations.product_list_empty_message, textAlign: TextAlign.center, style: themeData.textTheme.bodyMedium?.apply( - color: themeData.colorScheme.onBackground, + color: themeData.colorScheme.onSurface, ), ), EMPTY_WIDGET, diff --git a/packages/smooth_app/lib/pages/product/edit_image_button.dart b/packages/smooth_app/lib/pages/product/edit_image_button.dart index bc644102552..dd30c53526f 100644 --- a/packages/smooth_app/lib/pages/product/edit_image_button.dart +++ b/packages/smooth_app/lib/pages/product/edit_image_button.dart @@ -33,20 +33,20 @@ class EditImageButton extends StatelessWidget { child: OutlinedButton.icon( icon: Icon(iconData), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(colorScheme.onPrimary), - shape: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all(colorScheme.onPrimary), + shape: WidgetStateProperty.all( const RoundedRectangleBorder(borderRadius: ROUNDED_BORDER_RADIUS), ), side: borderWidth == null ? null - : MaterialStateBorderSide.resolveWith( + : WidgetStateBorderSide.resolveWith( (_) => BorderSide( color: colorScheme.primary, width: borderWidth!, ), ), padding: _centerContent - ? MaterialStateProperty.all( + ? WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: LARGE_SPACE, ), diff --git a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart index 6c4e248066c..4c0a003929b 100644 --- a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart +++ b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart @@ -324,7 +324,7 @@ Color _getSmoothCardColorAlternate(final BuildContext context, int index) { if (index.isOdd) { cardColor = PRIMARY_GREY_COLOR; } else { - cardColor = darkColorScheme.background; + cardColor = darkColorScheme.surface; } } diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart index 1f737bc5744..d78a52cce5e 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_page.dart @@ -294,7 +294,7 @@ class _EditOcrPageState extends State with UpToDateMixin { flex: 1, child: DecoratedBox( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadiusDirectional.only( topStart: ANGULAR_RADIUS, topEnd: ANGULAR_RADIUS, diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index ee44bec4fb5..e20901edfa2 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -416,11 +416,11 @@ class _ProductPageState extends State ), child: ElevatedButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsets.symmetric( horizontal: VERY_LARGE_SPACE, vertical: MEDIUM_SPACE), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart b/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart index 86b1a5dea6a..afa30d2b80d 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_add_nutrient_button.dart @@ -99,7 +99,7 @@ class NutritionAddNutrientButton extends StatelessWidget { } }, style: ButtonStyle( - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: ROUNDED_BORDER_RADIUS, side: BorderSide.none, diff --git a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart index 3a872cbbf39..6fed13681ec 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart @@ -322,7 +322,7 @@ class _NutritionPageLoadedState extends State value: _nutritionContainer.noNutritionData, onChanged: (final bool value) => setState(() => _nutritionContainer.noNutritionData = value), - trackColor: MaterialStateProperty.all( + trackColor: WidgetStateProperty.all( Theme.of(context).colorScheme.onPrimary), ), ), diff --git a/packages/smooth_app/lib/pages/product/product_incomplete_card.dart b/packages/smooth_app/lib/pages/product/product_incomplete_card.dart index ceba846b333..c60c7897639 100644 --- a/packages/smooth_app/lib/pages/product/product_incomplete_card.dart +++ b/packages/smooth_app/lib/pages/product/product_incomplete_card.dart @@ -111,13 +111,13 @@ class ProductIncompleteCard extends StatelessWidget { ), ), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( colorScheme.primary, ), - foregroundColor: MaterialStateProperty.all( + foregroundColor: WidgetStateProperty.all( colorScheme.onPrimary, ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder(borderRadius: ANGULAR_BORDER_RADIUS), ), ), diff --git a/packages/smooth_app/lib/pages/product/product_question_answers_options.dart b/packages/smooth_app/lib/pages/product/product_question_answers_options.dart index efeac877bd0..d9e1c31e72a 100644 --- a/packages/smooth_app/lib/pages/product/product_question_answers_options.dart +++ b/packages/smooth_app/lib/pages/product/product_question_answers_options.dart @@ -91,7 +91,7 @@ class ProductQuestionAnswersOptions extends StatelessWidget { child: TextButton( onPressed: () => onAnswer(insightAnnotation), style: ButtonStyle( - backgroundColor: MaterialStateProperty.all(backgroundColor), + backgroundColor: WidgetStateProperty.all(backgroundColor), ), child: Text( buttonText, diff --git a/packages/smooth_app/lib/pages/scan/scan_header.dart b/packages/smooth_app/lib/pages/scan/scan_header.dart index ab419653504..53cbe5bbb6e 100644 --- a/packages/smooth_app/lib/pages/scan/scan_header.dart +++ b/packages/smooth_app/lib/pages/scan/scan_header.dart @@ -24,7 +24,7 @@ class _ScanHeaderState extends State { final ContinuousScanModel model = context.watch(); final ButtonStyle buttonStyle = ButtonStyle( - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(18.0)), ), diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index f1a4f4401ea..26f22f14e30 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -64,7 +64,7 @@ class _ScanPageState extends State { color: Colors.white, child: SafeArea( child: Container( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Column( children: [ if (hasACamera) diff --git a/packages/smooth_app/lib/pages/scan/search_history_view.dart b/packages/smooth_app/lib/pages/scan/search_history_view.dart index 975da30935f..a4b0a94507a 100644 --- a/packages/smooth_app/lib/pages/scan/search_history_view.dart +++ b/packages/smooth_app/lib/pages/scan/search_history_view.dart @@ -46,8 +46,8 @@ class _SearchHistoryViewState extends State { data: ListTileThemeData( titleTextStyle: const TextStyle(fontSize: 20.0), minLeadingWidth: 18.0, - iconColor: Theme.of(context).colorScheme.onBackground, - textColor: Theme.of(context).colorScheme.onBackground, + iconColor: Theme.of(context).colorScheme.onSurface, + textColor: Theme.of(context).colorScheme.onSurface, ), child: ListView.builder( itemBuilder: (BuildContext context, int i) { diff --git a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart index 028ad5d5f38..42108e73d1e 100644 --- a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart +++ b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart @@ -150,11 +150,10 @@ class _ForgotPasswordPageState extends State } }, style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: - MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/user_management/login_page.dart b/packages/smooth_app/lib/pages/user_management/login_page.dart index fbd7e963e49..cbda47ad48b 100644 --- a/packages/smooth_app/lib/pages/user_management/login_page.dart +++ b/packages/smooth_app/lib/pages/user_management/login_page.dart @@ -221,12 +221,12 @@ class _LoginPageState extends State with TraceableClientMixin { ElevatedButton( onPressed: () => _login(context), style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: MaterialStateProperty.all< - RoundedRectangleBorder>( + shape: + WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -249,14 +249,14 @@ class _LoginPageState extends State with TraceableClientMixin { //Forgot password TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsets.symmetric( vertical: 10.0, horizontal: VERY_LARGE_SPACE, ), ), shape: - MaterialStateProperty.all( + WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -304,15 +304,15 @@ class _LoginPageState extends State with TraceableClientMixin { } }, style: ButtonStyle( - side: MaterialStateProperty.all( + side: WidgetStateProperty.all( BorderSide( color: theme.colorScheme.primary, width: 2.0), ), - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height), ), - shape: MaterialStateProperty.all< - RoundedRectangleBorder>( + shape: + WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart index 48f2713516f..8bbd6b10238 100644 --- a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart +++ b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart @@ -56,11 +56,11 @@ class _SignUpPageState extends State with TraceableClientMixin { final AppLocalizations appLocalizations = AppLocalizations.of(context); final Size size = MediaQuery.sizeOf(context); - Color getCheckBoxColor(Set states) { - const Set interactiveStates = { - MaterialState.pressed, - MaterialState.hovered, - MaterialState.focused, + Color getCheckBoxColor(Set states) { + const Set interactiveStates = { + WidgetState.pressed, + WidgetState.hovered, + WidgetState.focused, }; if (states.any(interactiveStates.contains)) { return theme.colorScheme.onSurface; @@ -236,14 +236,14 @@ class _SignUpPageState extends State with TraceableClientMixin { child: Checkbox( value: _foodProducer, fillColor: - MaterialStateProperty.resolveWith(getCheckBoxColor), + WidgetStateProperty.resolveWith(getCheckBoxColor), onChanged: (_) {}, ), ), title: Text( appLocalizations.sign_up_page_producer_checkbox, style: theme.textTheme.bodyMedium - ?.copyWith(color: theme.colorScheme.onBackground), + ?.copyWith(color: theme.colorScheme.onSurface), ), ), if (_foodProducer) ...[ @@ -274,24 +274,24 @@ class _SignUpPageState extends State with TraceableClientMixin { child: Checkbox( value: _subscribe, fillColor: - MaterialStateProperty.resolveWith(getCheckBoxColor), + WidgetStateProperty.resolveWith(getCheckBoxColor), onChanged: (_) {}, ), ), title: Text( appLocalizations.sign_up_page_subscribe_checkbox, style: theme.textTheme.bodyMedium - ?.copyWith(color: theme.colorScheme.onBackground), + ?.copyWith(color: theme.colorScheme.onSurface), ), ), const SizedBox(height: space), ElevatedButton( onPressed: () async => _signUp(), style: ButtonStyle( - minimumSize: MaterialStateProperty.all( + minimumSize: WidgetStateProperty.all( Size(size.width * 0.5, theme.buttonTheme.height + 10), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), @@ -447,7 +447,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { final bool agree; final bool disagree; - final MaterialPropertyResolver checkboxColorResolver; + final WidgetPropertyResolver checkboxColorResolver; final ValueChanged onCheckboxChanged; @override @@ -470,7 +470,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { ignoring: true, child: Checkbox( value: agree, - fillColor: MaterialStateProperty.resolveWith( + fillColor: WidgetStateProperty.resolveWith( checkboxColorResolver, ), onChanged: (_) {}, @@ -485,7 +485,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { // additional space needed because of the next text span text: '${appLocalizations.sign_up_page_agree_text} ', style: theme.textTheme.bodyMedium?.copyWith( - color: theme.colorScheme.onBackground, + color: theme.colorScheme.onSurface, ), ), TextSpan( @@ -509,7 +509,7 @@ class _TermsOfUseCheckbox extends StatelessWidget { semanticLabel: appLocalizations.termsOfUse, Icons.info, color: checkboxColorResolver( - {MaterialState.selected}, + {WidgetState.selected}, ), ), ), diff --git a/packages/smooth_app/lib/smooth_category_picker_example.dart b/packages/smooth_app/lib/smooth_category_picker_example.dart index 48287c35432..86263096ff9 100644 --- a/packages/smooth_app/lib/smooth_category_picker_example.dart +++ b/packages/smooth_app/lib/smooth_category_picker_example.dart @@ -167,9 +167,8 @@ class _ExampleAppState extends State { foregroundColor: Colors.black, ), checkboxTheme: CheckboxTheme.of(context).copyWith( - fillColor: - MaterialStateColor.resolveWith((Set states) { - if (states.contains(MaterialState.selected)) { + fillColor: WidgetStateColor.resolveWith((Set states) { + if (states.contains(WidgetState.selected)) { return Colors.green; } return Colors.black38; diff --git a/packages/smooth_app/lib/themes/color_schemes.dart b/packages/smooth_app/lib/themes/color_schemes.dart index 9e31f3135f9..59bd71c4963 100644 --- a/packages/smooth_app/lib/themes/color_schemes.dart +++ b/packages/smooth_app/lib/themes/color_schemes.dart @@ -12,10 +12,8 @@ const ColorScheme lightColorScheme = ColorScheme( onSecondary: Color(0xFF000000), error: Color(0xFFEB5757), onError: Color(0xFFFFFFFF), - background: Color(0xFFFFFFFF), - onBackground: Color(0xFF000000), - surface: Color(0xFF85746C), - onSurface: Color(0xFFFFFFFF), + surface: Color(0xFFFFFFFF), + onSurface: Color(0xFF000000), ); const ColorScheme darkColorScheme = ColorScheme( @@ -27,10 +25,8 @@ const ColorScheme darkColorScheme = ColorScheme( onSecondary: Color(0xFFFFFFFF), error: Color(0xFFEB5757), onError: Color(0xFFFFFFFF), - background: Color(0xFF201A17), - onBackground: Color(0xFFFFFFFF), - surface: Color(0xFFEDE0DB), - onSurface: Color(0xFF000000), + surface: Color(0xFF201A17), + onSurface: Color(0xFFFFFFFF), ); const ColorScheme trueDarkColorScheme = ColorScheme( @@ -42,10 +38,8 @@ const ColorScheme trueDarkColorScheme = ColorScheme( onSecondary: Color(0xFFE1E1E1), error: Color(0xFFEA2B2B), onError: Color(0xFFE1E1E1), - background: Color(0xFF000000), - onBackground: Color(0xFFE1E1E1), surface: Color(0xFF000000), - onSurface: Color(0xFFE1E1E1), + onSurface: Color(0xFFFFFFFF), ); const String CONTRAST_LOW = 'Low'; diff --git a/packages/smooth_app/lib/themes/smooth_theme.dart b/packages/smooth_app/lib/themes/smooth_theme.dart index 301342c3123..1d41a28ecbe 100644 --- a/packages/smooth_app/lib/themes/smooth_theme.dart +++ b/packages/smooth_app/lib/themes/smooth_theme.dart @@ -47,7 +47,7 @@ class SmoothTheme { ], colorScheme: myColorScheme, canvasColor: themeProvider.currentTheme == THEME_AMOLED - ? myColorScheme.background + ? myColorScheme.surface : null, bottomNavigationBarTheme: BottomNavigationBarThemeData( selectedIconTheme: const IconThemeData(size: 24.0), @@ -61,11 +61,10 @@ class SmoothTheme { ), elevatedButtonTheme: ElevatedButtonThemeData( style: ButtonStyle( - backgroundColor: MaterialStateProperty.resolveWith( - (Set states) => - states.contains(MaterialState.disabled) - ? Colors.grey - : myColorScheme.primary, + backgroundColor: WidgetStateProperty.resolveWith( + (Set states) => states.contains(WidgetState.disabled) + ? Colors.grey + : myColorScheme.primary, ), ), ), @@ -76,8 +75,8 @@ class SmoothTheme { ? getTextTheme(themeProvider, textContrastProvider) : _TEXT_THEME, appBarTheme: AppBarTheme( - color: myColorScheme.background, - foregroundColor: myColorScheme.onBackground, + color: myColorScheme.surface, + foregroundColor: myColorScheme.onSurface, systemOverlayStyle: SystemUiOverlayStyle.light, ), dividerColor: const Color(0xFFdfdfdf), @@ -85,59 +84,59 @@ class SmoothTheme { fillColor: myColorScheme.secondary, ), iconTheme: IconThemeData( - color: myColorScheme.onBackground, + color: myColorScheme.onSurface, ), snackBarTheme: SnackBarThemeData( contentTextStyle: _TEXT_THEME.bodyMedium?.copyWith(color: myColorScheme.onPrimary), actionTextColor: myColorScheme.onPrimary, - backgroundColor: myColorScheme.onBackground, + backgroundColor: myColorScheme.onSurface, ), bannerTheme: MaterialBannerThemeData( contentTextStyle: TextStyle(color: myColorScheme.onSecondary), backgroundColor: myColorScheme.secondary, ), checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; }), ), radioTheme: RadioThemeData( - fillColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + fillColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; }), ), switchTheme: SwitchThemeData( - thumbColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + thumbColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; }), - trackColor: MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.disabled)) { + trackColor: + WidgetStateProperty.resolveWith((Set states) { + if (states.contains(WidgetState.disabled)) { return null; } - if (states.contains(MaterialState.selected)) { + if (states.contains(WidgetState.selected)) { return myColorScheme.primary; } return null; diff --git a/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart b/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart index c079a64c370..7a2de39e52a 100644 --- a/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart +++ b/packages/smooth_app/lib/widgets/ranking_floating_action_button.dart @@ -29,7 +29,7 @@ class RankingFloatingActionButton extends StatelessWidget { child: ElevatedButton.icon( onPressed: onPressed, style: ButtonStyle( - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( const RoundedRectangleBorder( borderRadius: CIRCULAR_BORDER_RADIUS, ), diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index d346af35141..811c148d149 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -924,10 +924,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.19.0" iso_countries: dependency: "direct main" description: @@ -964,26 +964,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -1052,10 +1052,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" mgrs_dart: dependency: transitive description: @@ -1599,10 +1599,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" typed_data: dependency: transitive description: @@ -1743,10 +1743,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" watcher: dependency: transitive description: @@ -1852,5 +1852,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.3 <4.0.0" + dart: ">=3.4.0 <4.0.0" flutter: ">=3.19.0" diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index c0f7b8ff438..113f6f7bf8d 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.0.0+734 publish_to: "none" environment: - sdk: '>=3.3.3 <4.0.0' + sdk: '>=3.4.0 <4.0.0' dependencies: flutter: @@ -54,7 +54,7 @@ dependencies: auto_size_text: 3.0.0 crop_image: 1.0.13 shared_preferences: 2.2.3 - intl: 0.18.1 + intl: 0.19.0 collection: 1.18.0 path: 1.9.0 path_provider: 2.1.3 From 1ff9a0a9b01c39439b258b5b1aa9db3b8123c051 Mon Sep 17 00:00:00 2001 From: Jordan Nnabugwu Date: Thu, 4 Jul 2024 09:29:24 -0400 Subject: [PATCH 58/85] feat: Spellchecker on product name 5415 (#5451) * feat: added spell check configuration to the smooth text form * feat: added spellcheck to product field in basic details page * fix: fixed formatting --- .../widgets/smooth_text_form_field.dart | 4 + .../pages/product/add_basic_details_page.dart | 84 +++++++++++++------ 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart index 8ea02fadb2a..ce4d0fc6166 100644 --- a/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart @@ -24,6 +24,7 @@ class SmoothTextFormField extends StatefulWidget { this.onFieldSubmitted, this.autofocus, this.focusNode, + this.spellCheckConfiguration, }); final TextFieldTypes type; @@ -40,6 +41,7 @@ class SmoothTextFormField extends StatefulWidget { final ValueChanged? onFieldSubmitted; final bool? autofocus; final FocusNode? focusNode; + final SpellCheckConfiguration? spellCheckConfiguration; @override State createState() => _SmoothTextFormFieldState(); @@ -83,6 +85,8 @@ class _SmoothTextFormFieldState extends State { setState(() {}); } }, + spellCheckConfiguration: widget.spellCheckConfiguration ?? + const SpellCheckConfiguration.disabled(), onFieldSubmitted: widget.onFieldSubmitted, style: TextStyle(fontSize: textSize), cursorHeight: textSize * (textStyle.height ?? 1.4), diff --git a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart index b6e272b3e48..c59d5fdd03d 100644 --- a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart +++ b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart @@ -1,14 +1,19 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/background/background_task_details.dart'; import 'package:smooth_app/cards/product_cards/product_image_carousel.dart'; +import 'package:smooth_app/data_models/preferences/user_preferences.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; +import 'package:smooth_app/helpers/provider_helper.dart'; import 'package:smooth_app/pages/input/smooth_autocomplete_text_field.dart'; import 'package:smooth_app/pages/input/unfocus_field_when_tap_outside.dart'; +import 'package:smooth_app/pages/preferences/user_preferences_dev_mode.dart'; import 'package:smooth_app/pages/product/common/product_buttons.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/may_exit_page_helper.dart'; @@ -123,31 +128,62 @@ class _AddBasicDetailsPageState extends State { ), ), SizedBox(height: _heightSpace), - if (_multilingualHelper.isMonolingual()) - SmoothTextFormField( - controller: _productNameController, - type: TextFieldTypes.PLAIN_TEXT, - hintText: appLocalizations.product_name, - ) - else - Card( - child: Column( - children: [ - _multilingualHelper.getLanguageSelector( - setState: setState, - product: _product, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: SmoothTextFormField( - controller: _productNameController, - type: TextFieldTypes.PLAIN_TEXT, - hintText: appLocalizations.product_name, - ), + ConsumerFilter( + buildWhen: ( + UserPreferences? previousValue, + UserPreferences currentValue, + ) { + return previousValue?.getFlag(UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr) != + currentValue.getFlag(UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr); + }, + builder: (BuildContext context, UserPreferences prefs, + Widget? child) { + if (_multilingualHelper.isMonolingual()) { + return SmoothTextFormField( + controller: _productNameController, + type: TextFieldTypes.PLAIN_TEXT, + hintText: appLocalizations.product_name, + spellCheckConfiguration: (prefs.getFlag( + UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr) ?? + false) && + (Platform.isAndroid || Platform.isIOS) + ? const SpellCheckConfiguration() + : const SpellCheckConfiguration.disabled(), + ); + } else { + return Card( + child: Column( + children: [ + _multilingualHelper.getLanguageSelector( + setState: setState, + product: _product, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: SmoothTextFormField( + controller: _productNameController, + type: TextFieldTypes.PLAIN_TEXT, + hintText: appLocalizations.product_name, + spellCheckConfiguration: (prefs.getFlag( + UserPreferencesDevMode + .userPreferencesFlagSpellCheckerOnOcr) ?? + false) && + (Platform.isAndroid || + Platform.isIOS) + ? const SpellCheckConfiguration() + : const SpellCheckConfiguration + .disabled(), + ), + ), + ], ), - ], - ), - ), + ); + } + }, + ), SizedBox(height: _heightSpace), LayoutBuilder( builder: ( From b2fbb755741884aae8371e86baa5f931d1c41e26 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 4 Jul 2024 15:30:05 +0200 Subject: [PATCH 59/85] Allow the URL of a translated image to be null (#5446) --- .../lib/data_models/news_feed/newsfeed_json.dart | 14 ++++++++++---- .../lib/data_models/news_feed/newsfeed_model.dart | 2 +- .../scan/carousel/main_card/scan_tagline.dart | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart index e10b4be3901..936c0f3e199 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_json.dart @@ -121,7 +121,9 @@ class _TagLineItemNewsItem { startDate: startDate, endDate: endDate, style: style?.toTagLineStyle(), - image: translation.image?.toTagLineImage(), + image: translation.image?.overridesContent == true + ? translation.image?.toTagLineImage() + : null, ); } @@ -210,20 +212,22 @@ class _TagLineItemNewsTranslationDefault extends _TagLineItemNewsTranslation { _TagLineItemNewsTranslationDefault.fromJson(Map json) : assert((json['title'] as String).isNotEmpty), assert((json['message'] as String).isNotEmpty), + assert(json['image'] == null || + ((json['image'] as Map)['url'] as String) + .isNotEmpty), super.fromJson(json); } class _TagLineNewsImage { _TagLineNewsImage.fromJson(Map json) - : assert((json['url'] as String).isNotEmpty), - assert(json['width'] == null || + : assert(json['width'] == null || ((json['width'] as num) >= 0.0 && (json['width'] as num) <= 1.0)), assert(json['alt'] == null || (json['alt'] as String).isNotEmpty), url = json['url'], width = json['width'], alt = json['alt']; - final String url; + final String? url; final double? width; final String? alt; @@ -234,6 +238,8 @@ class _TagLineNewsImage { alt: alt, ); } + + bool get overridesContent => url != null || width != null || alt != null; } class _TagLineNewsStyle { diff --git a/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart b/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart index c9d6cd21de0..a4790124990 100644 --- a/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart +++ b/packages/smooth_app/lib/data_models/news_feed/newsfeed_model.dart @@ -118,7 +118,7 @@ class AppNewsImage { this.alt, }); - final String src; + final String? src; final double? width; final String? alt; diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart index d3e029655cf..8404fe114e1 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_tagline.dart @@ -302,7 +302,7 @@ class _TagLineContentBodyState extends State<_TagLineContentBody> { } Widget _image() { - if (widget.image!.src.endsWith('svg')) { + if (widget.image!.src?.endsWith('svg') == true) { return SvgCache( widget.image!.src, semanticsLabel: widget.image!.alt, @@ -323,7 +323,7 @@ class _TagLineContentBodyState extends State<_TagLineContentBody> { return EMPTY_WIDGET; }, - widget.image!.src, + widget.image!.src ?? '-', ); } } From ca749bca0d0ec2cb95e000ceab8e9984f478aa04 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Thu, 4 Jul 2024 15:30:37 +0200 Subject: [PATCH 60/85] Save the date when the language is changed (#5443) --- .../lib/data_models/preferences/user_preferences.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart index 012fa624aec..f5c4d3aa077 100644 --- a/packages/smooth_app/lib/data_models/preferences/user_preferences.dart +++ b/packages/smooth_app/lib/data_models/preferences/user_preferences.dart @@ -68,6 +68,8 @@ class UserPreferences extends ChangeNotifier { static const String _TAG_CURRENT_COLOR_SCHEME = 'currentColorScheme'; static const String _TAG_CURRENT_CONTRAST_MODE = 'contrastMode'; static const String _TAG_USER_COUNTRY_CODE = 'userCountry'; + static const String _TAG_USER_COUNTRY_CODE_LAST_UPDATE = + 'userCountryLastUpdate'; static const String _TAG_USER_CURRENCY_CODE = 'userCurrency'; static const String _TAG_LAST_VISITED_ONBOARDING_PAGE = 'lastVisitedOnboardingPage'; @@ -227,6 +229,10 @@ class UserPreferences extends ChangeNotifier { /// Please use [ProductQuery.setCountry] as interface Future setUserCountryCode(final String countryCode) async { await _sharedPreferences.setString(_TAG_USER_COUNTRY_CODE, countryCode); + await _sharedPreferences.setInt( + _TAG_USER_COUNTRY_CODE_LAST_UPDATE, + DateTime.now().millisecondsSinceEpoch, + ); notifyListeners(); } From 173c34d36a9574be8746871360495bb5fda9e9da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 08:22:01 +0200 Subject: [PATCH 61/85] chore(deps): bump webview_flutter_android in /packages/smooth_app (#5476) Bumps [webview_flutter_android](https://github.com/flutter/packages/tree/main/packages/webview_flutter) from 3.16.1 to 3.16.4. - [Release notes](https://github.com/flutter/packages/releases) - [Commits](https://github.com/flutter/packages/commits/webview_flutter_android-v3.16.4/packages/webview_flutter) --- updated-dependencies: - dependency-name: webview_flutter_android dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/pubspec.lock | 4 ++-- packages/smooth_app/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 811c148d149..0edac24f5f7 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -1783,10 +1783,10 @@ packages: dependency: "direct main" description: name: webview_flutter_android - sha256: dad3313c9ead95517bb1cae5e1c9d20ba83729d5a59e5e83c0a2d66203f27f91 + sha256: f42447ca49523f11d8f70abea55ea211b3cafe172dd7a0e7ac007bb35dd356dc url: "https://pub.dev" source: hosted - version: "3.16.1" + version: "3.16.4" webview_flutter_platform_interface: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 113f6f7bf8d..7855b4b00e5 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: shimmer: ^3.0.0 rive: 0.13.4 webview_flutter: 4.7.0 - webview_flutter_android: 3.16.1 + webview_flutter_android: 3.16.4 webview_flutter_wkwebview: 3.13.0 flutter_custom_tabs: 2.0.0+1 flutter_image_compress: 2.2.0 From 68e814064a229ffcf31057ee98fb7c634f90f4b6 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 5 Jul 2024 08:37:24 +0200 Subject: [PATCH 62/85] fix: Raster cache should support `ErrorBuilder` (#5475) * Raster cache should support `ErrorBuilder` * Prevent duplicated code --- .../cards/category_cards/raster_cache.dart | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/smooth_app/lib/cards/category_cards/raster_cache.dart b/packages/smooth_app/lib/cards/category_cards/raster_cache.dart index 312ca179244..dd86ec4c515 100644 --- a/packages/smooth_app/lib/cards/category_cards/raster_cache.dart +++ b/packages/smooth_app/lib/cards/category_cards/raster_cache.dart @@ -17,6 +17,7 @@ class RasterCache extends AbstractCache { if (fullFilenames.isEmpty) { return getDefaultUnknown(); } + return Image.network( iconUrl!, width: width, @@ -30,15 +31,25 @@ class RasterCache extends AbstractCache { if (loadingProgress == null) { return child; } - return RasterAsyncAsset( - AssetCacheHelper( - fullFilenames, - iconUrl!, - width: width, - height: height, - ), - ); + return _localAssetWidget(fullFilenames); }, + errorBuilder: ( + final BuildContext context, + final Object error, + final StackTrace? stackTrace, + ) => + _localAssetWidget(fullFilenames), + ); + } + + RasterAsyncAsset _localAssetWidget(List fullFilenames) { + return RasterAsyncAsset( + AssetCacheHelper( + fullFilenames, + iconUrl!, + width: width, + height: height, + ), ); } } From 3a4c0c94170bc68c1f606a1eda143281737f7ba6 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Fri, 5 Jul 2024 17:55:29 +0200 Subject: [PATCH 63/85] feat: new parameters for uploadProof (#5480) Impacted files: * `background_task_add_prices.dart`: 4 new parameters for `uploadProof` * `pubspec.lock`: wtf * `pubspec.yaml`: upgraded to off-dart 3.12.0 --- .../lib/background/background_task_add_price.dart | 4 ++++ packages/smooth_app/pubspec.lock | 6 +++--- packages/smooth_app/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/smooth_app/lib/background/background_task_add_price.dart b/packages/smooth_app/lib/background/background_task_add_price.dart index bff36bc9f2c..a17b2ff50c2 100644 --- a/packages/smooth_app/lib/background/background_task_add_price.dart +++ b/packages/smooth_app/lib/background/background_task_add_price.dart @@ -360,6 +360,10 @@ class BackgroundTaskAddPrice extends BackgroundTask { HttpHelper().imagineMediaType(initialImageUri.path)!; final MaybeError uploadProof = await OpenPricesAPIClient.uploadProof( proofType: proofType, + date: date, + currency: currency, + locationOSMId: locationOSMId, + locationOSMType: locationOSMType, imageUri: initialImageUri, mediaType: initialMediaType, bearerToken: bearerToken, diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 0edac24f5f7..087fac1f295 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -1108,10 +1108,10 @@ packages: dependency: "direct main" description: name: openfoodfacts - sha256: "90a853e7536d0f97a665b18cd602055215520bf424765ef06930e4be25b760ba" + sha256: b8e90057fc04ecb407bdd48758172fc8200483ae15e926d6825fc3bd6a4d2468 url: "https://pub.dev" source: hosted - version: "3.11.0" + version: "3.12.0" openfoodfacts_flutter_lints: dependency: "direct dev" description: @@ -1853,4 +1853,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.4.0 <4.0.0" - flutter: ">=3.19.0" + flutter: ">=3.22.0" diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 7855b4b00e5..f5a3f06855b 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -100,7 +100,7 @@ dependencies: path: ../scanner/zxing - openfoodfacts: 3.11.0 + openfoodfacts: 3.12.0 # openfoodfacts: # path: ../../../openfoodfacts-dart From f24255ba4beb59cd4bda6d492e4c51df9f70db00 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Fri, 5 Jul 2024 17:57:14 +0200 Subject: [PATCH 64/85] Absolutely useless (#5474) --- .../lib/pages/product/new_product_page.dart | 5 +---- packages/smooth_app/macos/Podfile.lock | 4 ++-- packages/smooth_app/pubspec.lock | 16 ---------------- packages/smooth_app/pubspec.yaml | 1 - 4 files changed, 3 insertions(+), 23 deletions(-) diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index e20901edfa2..384904f2b2b 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -1,4 +1,3 @@ -import 'package:assorted_layout_widgets/assorted_layout_widgets.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -464,9 +463,7 @@ class _ProductPageState extends State appLocalizations.user_list_subtitle_product, style: Theme.of(context).textTheme.displaySmall, ), - WrapSuper( - wrapType: WrapType.fit, - wrapFit: WrapFit.proportional, + Wrap( spacing: VERY_SMALL_SPACE, children: children, ), diff --git a/packages/smooth_app/macos/Podfile.lock b/packages/smooth_app/macos/Podfile.lock index b35a6160333..a01e826ae0d 100644 --- a/packages/smooth_app/macos/Podfile.lock +++ b/packages/smooth_app/macos/Podfile.lock @@ -15,7 +15,7 @@ PODS: - FlutterMacOS (1.0.0) - in_app_review (0.2.0): - FlutterMacOS - - mobile_scanner (3.5.2): + - mobile_scanner (3.5.6): - FlutterMacOS - package_info_plus (0.0.1): - FlutterMacOS @@ -113,7 +113,7 @@ SPEC CHECKSUMS: flutter_secure_storage_macos: 59459653abe1adb92abbc8ea747d79f8d19866c9 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 - mobile_scanner: 621cf2c34e1c74ae7ce5c6793638ab600723bdea + mobile_scanner: 54ceceae0c8da2457e26a362a6be5c61154b1829 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149 diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 087fac1f295..ce041dcc8e2 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -77,14 +77,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.0" - assorted_layout_widgets: - dependency: "direct main" - description: - name: assorted_layout_widgets - sha256: "7d7688db393f02b8811f28bacdd9d791cf218f5805dee925f913a1849858e192" - url: "https://pub.dev" - source: hosted - version: "9.0.1" async: dependency: "direct main" description: @@ -1040,14 +1032,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.1" - matrix4_transform: - dependency: transitive - description: - name: matrix4_transform - sha256: "42c42610deecc382be2653f4a21358537401bd5b027c168a174c7c6a64959908" - url: "https://pub.dev" - source: hosted - version: "3.0.1" meta: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index f5a3f06855b..1643c916804 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -42,7 +42,6 @@ dependencies: sqflite_common_ffi: 2.3.3 url_launcher: 6.1.3 visibility_detector: 0.4.0+2 - assorted_layout_widgets: 9.0.1 app_settings: 5.1.1 diacritic: 0.1.5 app_store_shared: From d83d33b574264b286de7b0c9b4c8f2b4f38a6882 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sun, 7 Jul 2024 11:03:34 +0200 Subject: [PATCH 65/85] Fix iOS crash (#5482) --- packages/smooth_app/ios/Podfile | 2 +- packages/smooth_app/ios/Podfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/ios/Podfile b/packages/smooth_app/ios/Podfile index b8501cec908..88e2e54a0cd 100644 --- a/packages/smooth_app/ios/Podfile +++ b/packages/smooth_app/ios/Podfile @@ -39,7 +39,7 @@ post_install do |installer| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', diff --git a/packages/smooth_app/ios/Podfile.lock b/packages/smooth_app/ios/Podfile.lock index 04989447e33..d81cc120361 100644 --- a/packages/smooth_app/ios/Podfile.lock +++ b/packages/smooth_app/ios/Podfile.lock @@ -282,7 +282,7 @@ SPEC CHECKSUMS: GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d - integration_test: 13825b8a9334a850581300559b8839134b124670 + integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4 iso_countries: eb09d40f388e4c65e291e0bb36a701dfe7de6c74 libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d @@ -311,6 +311,6 @@ SPEC CHECKSUMS: url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36 -PODFILE CHECKSUM: a2ded99d2ba03f677e98efb8fb92d57b3a65b96f +PODFILE CHECKSUM: 31bd95b3ebe08a1371aec307f223993946c837a3 COCOAPODS: 1.15.2 From 48e5e4f2cb1ccded0df154c4205d26c1968c5124 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sun, 7 Jul 2024 11:38:13 +0200 Subject: [PATCH 66/85] Remove 2 unused files (#5472) --- packages/smooth_app/assets/animations/off | Bin 114843 -> 0 bytes .../lib/smooth_category_picker_example.dart | 222 ------------------ 2 files changed, 222 deletions(-) delete mode 100644 packages/smooth_app/assets/animations/off delete mode 100644 packages/smooth_app/lib/smooth_category_picker_example.dart diff --git a/packages/smooth_app/assets/animations/off b/packages/smooth_app/assets/animations/off deleted file mode 100644 index 969af53419c6524aae66eef4ec28c4b3c7ba7853..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114843 zcmdpf2V7Lg_wVk)f}*=1Snk*xv5Sa^O4xhvf(3i@7BxnLioFF<)M)Izcfk^S*BGP5 zSlGL3NvyHPn%EP2u*Db)@0^*t%OYrA`@i>okI!c>b7#(c=ggTieeRi7@k)Jv!}Whk z956039x^^KJuq%I?l2xS-Z!l>{b)3}|0;u{h{5RVZ%;_-+^$4?uN-AM&iOH>EV{}C%=vMjA;j$WQD$bQp+f%Hvo`wH zVday|3I@YS-eB_0r?Xgnz@Tns19$|q=-a7ZLQD5H*bpKa^A;=t9+GsGFgSZsGyaKtIkymiPY45x_3Qpl^ z*zVesd6NAN;%V-96h#Bsjq}LPYB9K~Io&C8G)2N?zR2TAk-m9S%z8sq!W|)#9mtK> zo1VUoLf?YT4bz}u0)~0L%`P~_LBl9F^exyt z!7D{7)rBm@$~46)OsaYsRX8fS>~A_MrPN6FH$D9<6qM>jJw=m8z27O`2usn~KBDzb ztHQM)>$QLpKXW887_JEtRuH+@@yj;la$vlmq6-7L#NQe?$gqV61?h6&VP2k@a@Wg$ z?!to_&>wcFvvhw1(||NyU|N!9h#ar?;W-d9<{d44CidPOo`hK*-E%_ES2Q9sr@API8x!nf|9gYT(ce1qgQH{We2-)+74&eC)}skZOoTldew zHwDxArb6(RH;t4F-@1PezNdNdozmwU58nxt?@k}$yVHC4*8OwvO~KyBH;t4F-@1Pe zzNdTfO=kNzty=@jY=@SmC*`{rXFn6>t?60Hq6@tj*FU?m%wf%l?w^DCEW{i+@J7rf z2Ncn}jiD(8n`h`bfSxh7M^fkBiDnD5Hv=FK$utiGxqYpiB5STrg-9Z+=tsc?>N${` z>rlRf($PfLem<2$Z@qT6xByIkS%d>Nhfy|%bH8`kAd)rVkvkc$&u`b$c|{i_Hk>5X zTCcOYHSA-ZO>|)(Mt6Fm^Rhd-L-mfXvq_^y{n!3fOfv z9bgfwJ&cVo2tWpG8Q;BWpMJ@5@SLRQ}e<3CW4g5@5vJH_=dcveCb3 z!jQzI(lrgdL0n)o8e-x03k&W1tz&Fs|FFCnipJoZ&`u6Aw!)mj^lHPuz-8ypJa642*W6&-#fiIB! z&3N9jVq<|?*7|-$x5Kc|#2HGL-$@KD>(r)i(}dn4iEYV?@4N+@?O2bF8N$r=q*eX* z#SB25A85p3yWTkAG$3E2eti=ACv;1!rqnd&!FGYSJX;)QxAxvy#tz}ZUg6aS&}^CW z!W3p?6auk)ngh_|dxMX!Z_9+_?&f@!#eYoItWjxw9FURxv`w*a+Z&B_lE}tSoKo|` zl>|AmE+;C#+{#Q>i`C??*|2bbjx8pVa_xOx(zzdNYjSd;MO3N?vu*0WPc4k1X5%L! z*#JON;wWEDu8tVr6`sVa72OzR+xyzdMgWoyj9BH6dBk}9^+R5r@5UI_Xsk#c$3GFJ zeMd9XMl1%7-WM?03fMAiAlWN88OC< z_0`n!Zj6s08|3=fVovEMq%PYK<1}!jZbgh>b1ZA*!pyO>T#`$TyKkd~<5Pb~BAuXR zD;bWJOuL`T+O38jCEr&v1SVnzEC_S!?g{-9%|+RJkhvHwgyLL<;ejsF`pN=Pde#>N zIDF<7QTeO^2=Kw8EhysRT*88BBH3oiXP0igswl`CMW8r6(BM#~{nS>V6w$sXM6$Z) zAELDPAScL4om&c^d&Rll(WUJqb3UjIzO9X_YbS3aO?DdR+AxEi_(T7wxXa`YX%hV zoP~0=_Fiz3d2>J43&L4)G^P;BecW!KlZ<=wv#xfnDv#FHZoQl0Y}!GQXjeMxN<}HC zQtfk7G%V6WB+c5MfE=UBv_%Z6GH2Wrp46E_bO8z|WS$jrusM#+J;Ka!S!G-_7<;_} z_;8mRt3K5&TW=rHtk<%p!6&Q<#o15Yb=c#-0*Wz0`Ysb zR*(whgKD+3S8GAZv_rM(S4XGVP-UG!j;@H(qU{jMOH8c&Bb825C*>}17|jd84RUG zaO8J8iiH~u#YHS3yDK7@$38SJA*okgBlIOzp{HTpD+FhPN8xupuut<)90Q6f-X0jm zmfZtJElqoL>z+*Uv*75om35H}4m`5M=@eOTbLY-Q{MsJ;O`A4l;;0CEwWQ>_H6bhy zgn4z|C1cCcJ{tPhlCkAsEI}gtfg(xox~X>nP&kG!iGeV^r_ULwNN$nnXp5!*Q8{eq*&f-a_HY&-9l z!SvbI5xN)>C^!+gPhc+BVQ1}mk@E;Z? z{DY`QLu6Dw9N4;tYSEL8=H6I~romt=Yupyj#%FZMW@aNb7`&NbxCWy(AAFc_H0Qh2 zc*h@xcHf#722W>RJqtu-Y5jukV1wzR57O>lh0|yH2rr8y8F6AK)n6(7oCl zxU0=ie9%{KtMUcTw5r5g8XO3SwN85&fgKjEg2Etfq+cy!xE8d7zLh@HNFglEIM&qHnu}Q0_{KS{@jf;eOj|k2 zih!$v)$lEh?}N;Qb~!~kt96Dzq~<+ErNzhL>FT_gX*d=r%H1Z#?4{*luJx&)bW-KkEkYKGlV=4Bf6)0*& zE~HQcf!O_PA=?!>d&Wp7IUgOUDT8m7(bUpaCi2w(`ZgG89~-_zldA2^C&&*gPUMxH zT?abU2jHR<#|Lz9lEo7?X;KQrluKbuGa$aW2W#^OoA1T`w<0&@ks^|ZyURM?iEYam zDUx%1Wv7Jc(%8z>&Bgg_9EimA^;=Ea0qIf>Aa~=va`$F;C($}G=$aF9SCbZ71UKZs zaFNvARX|kQzKwwa-t-9MHiG--L`RYQdc!PAU262<<>+}luZ%cs(bQ&AZIna=*X=;E zlQi^gu1SwS2~U?#)Tk{gBlFq>_2ox2#}Qn)I#ZqGY}r&z`r7&(3^WITObQpc>QIk> zi(>5VFv3Ynr@(@9T#!wWZw~>Al=h%L1IILDshpTGQ6#nZI0Y&8kVTWvuV^MJU%c(j ztEZVbw2L? zOfb0@r#Z`s%KHWD>OZMA>5J3c{y8|b9{r0`IecRqub!*C4>_`NukURT$gn#*L@A&R zHOtZQm4H@;F@#=PaEE8wINxuntQimX<^u z=bBU6h3SdP!;e8mdU|o3>HY={({oCg3QI2^r0h;Fj)U~JZ&H>@&QlvrgZXVpf_NBtGidgw?SL~Th? zKjHkI)DubT2{jS*6YkTrj!v@bt8*F%=M%2?(dJIFWpO2ka_cIHb#v9-}10tni=Gf@sfu#BUeK z%;eE9>OWpsQ+tn{is`rK3Rm8)QGe+`-gt-X@z1;mQ&)L1w@*QT_5Ai;lpaa-MNTcT z7mUQ=Pem66gGeHcB&i1rYx2U=;BSURKB}xI4w;$isk`kg!C|*WYn1`(cLJkbD5Hto zo6pVPlS*%Q>x+V$?9KH>L3BYXiCljFJx-GU@+i8d$jiUhp%k!yi7rav#?V&=DF)@# z8$H!@)3u&C|SO78G{dY3=yqy4oPK{#0gPa6;Iqom6Iw zH$9hMa8{I*ZSvUnNh&Mm`y@p%L=Q#|N%@(xFuY34!&?gD?E?}_;clV?-CX7(K^@}* z5=`N)q6FO-xkzxjmjr9JNpo5aZ`Rq+mxU{7Y81FA#nW@VMtnM-a!43c#+b_6 zB9k0h7{ByB#Uq9$VN8bc51^@a5CfL|J*{^;OHb{f(>iRQjKi|AM#|Ms(M6XSu;&FUhogFq5sn4pn9p)UmKw$Z@Lwc>$fQV1}*@l!VmplD?N z%ki4@*JR+7qL5(VGz%qx)=$d zI7zXe1Dz7amG>YD;(4JwITt7*3M{)oT!w;p3d(p?0(N169mGP10u$uASm;pv>8!x~%q*^eaUBxIl`$@Aj+Pz8fhZcP zPP&YRjjAK4hzHs9=0K`21XdUR0R01fnC->+QRhL?tq*C8^F>CkJeDNtg97CT9S_q2 z2zZe>o|d10N?u);H0gIEtmjY^&?O-|3gZBE zNuwyh`5Z6xcv=lwd0jnLFwR#}^>8xvfP&SSdO*SQ?t%r9`+C8OSg?YpVAI{|!B9k| z9vIi7WSSSsOI^vFsATCLB@^80F;^Ed^rO&wt~XlbZaeB&o3vekqwo!k-;G9YYvA%o zl7H<>{Y*mleV~Z6CqNezB9MH4{+5%pyfjji4(5&LWot@Jk@dFsewl;i>?VmCcU6<1 z8x~{?P!3@Sn?-WH%5f)glW2?t@zk2Hzt$7FUFEpQNO~X&2C!~A3k7)5NwB|XDA1Gh zUI|eW$}a8tDKE&C8rHog4v6OIWoQDSfMm8CK^{ApJa!s6<3`y|_C@)9&vy1!ytt3@ zILxc)g3JPmq>cw`8b&_@QL?BA#Pc`ZMpFV7h(^s9(?D?;)8ikl=AQG|5y2NEVxy z@JhgjDGoJbw;QEKvv~sf^;W1;vd6FFWn;)(UTGKjr$gOmZKR`Yj!zKC_w8bxQh|@^ z@p9d#QM|IHT~SSK(YcOJBBi)^(&G0|oKl^)rEKzfpBB9GB9PZqbg>+zw_M^NVnQ>g zbS85_y8LV8WL~*ltG1waSh!Uu8UK8eMtZlYgkQ^b&|dZ zR%#?<_eD*ra_Evn?mFRnJs>XQ6DRrNyr_^9N zNHTiz8(t~C0VKJr#2Y>CJ)wY;4Jsa?wMapv>;RAYCm{te&1wlR40%ovXRlDTSV`r^zLc1`A5c#V$6r=h>X-!O-gA*xO{z&J=^oP@b~U~QN&fxlkweay{hC*PtFn?;UncF) z*){cQEs}O&1)b8)N!uOr#Sx$zXHWdfs{^jNOSOB9T_k+QE={UmeU?LB9|#4%d$2)J zmxGJRrF%>Tk$>*$1irs1@5Ku zO0U%CyqXtW4CUuQf01;q>k_03kAdAr6_4Zm9K=4nZ-7Wfe{}(e7kUjjZ{$|hnlF%h zwv9MDg4e)8K?12!RncFcw=XY}d?ZYN^-Y4QOUoV5P6nG7xZ8WLO4#c41iSSc?lY`} zzp_gBn~`gG;G#xCpFqN9Gracd-&Y{b-hS_7uOqtE7s-XvOZC_L>nif(PE+Cqanr~F z5lq2LFGW7!wa5lgkCVfo&7!Y$&%R10-$ixRUn}7j+|uRSV{@KmSq4F7+)B)kJz-OjIxnDrSMj^<-MQ z84V2%&2+Fi6*|d%&$3TJYy3XeZY|VrC`#@HO73qaxtB&Rk6{pKivLG0Wr3}xrfy4h zAvy#oMMGU=;h`Z;XgwX{QF4%O{t1D0 z@;Cq_*UAp7HV4bN1H>1w%{xQBEh?L|b`G`e-c@=G;M7jal}!?*Ip6=q%SnB<2#VTc zk;98qPcEg#<96C8r=VnMAgU|v@z@E0UupPNfL~4c;Zc)V_{GDoCHy{xUl;iGhu?7c zjm2{+Q}8hxA8GhlfsYON*ny9|`1lnc_wezzQQvOTgc|7dhYcs)X#wX<^mXrrY&X)q zkOHs?0J}f2HQ+o4bfdVtgZoRcKZ9Ou`=n%STpVu94Dj|O5f<>m)qA8%y4BPUuXscP zU(-@AihvaSF48*~446bLF#%zi2Ys0UaX$tx&$iS^;4nXMNH?THV+%7U`c`rKl8F58 zruH7b8+njnt*WSw49;WVL}c9;k?CR()PPkPv3 z{{WW$TlP-qo0welfYAV}|EqEJe|~IUgCWQjU@$z~{{S`%;AC}wO2pQ}E$dExFIw$w zhTzF+OMLI%0|z80B_#KNEd;aC($nZ4Yt0;CjD^5L*#hCeF*Ngyvf=}X z^aXMs*fAdYy?*M#>>GF}@A>qg#^$ZO<@u)z1Z##PpJ?zkn+t|dZ5UhVO!QMZD0M3(YAX-olQ z!W3?AeL;?0SWQsYBsbls-tfYJwa=-Kc}YDQB`}PPi%(&d+Y5uGE?qh=?V}h_(a-vX zmYfe22zee;>ltq~7jA<*hftmia(5rT;7RedHceUcE%3a)Z4h!)kQ=+Jp+=@xI%1PT zx6XjB;kcimlq^ychUOzDV7Fb6>%4fKgPi#Vrk(fKK6S|b=S|@iA^+5LwQZ%U48z(& z6iA&D(VBE|&;eeSr`8mdKm9~aU3G5k5 zSkK;WfXjr%D9^>Yfy2u1WVzi@n~mz1*V%?AuVGZb6kLE?oYZeyhG*mXuR7AectJ%M z24ZxFCps@C2Uv(6$aShHQZU&!JuFkPYfuKmxxEXc zL{h!yKK&pj_uUcwbU3;og>dfdeA`YkZ*-Ktj5p^frGU~!7o`9Urw4-#m43*h@lNaY=0`QCKv9;e2_~oY+_z=00@a~B*X2GbYSTzS z#xRHUu*je3a=C6$b@TM7BB+k`w^1r}xo!nV!;GZYv~+2=7Uqy&FTP|`R?KU~tM=lw z`q$;8qBa3BcTTqjC!sjZ=_?=-6wR1gM%>}M=;sG8hU=?n}3|@Y@ z0;+lH2^eVR4c&}i?v=O)BkLVp<^(jYPrx>(8>5I$mro!P?`7Dh0Dee`I;zn6sA0I1NcNRQ? zTsEg%w&14x3zsdpua~$Yy|~O#>nX+uxy-`I!KGgHfA!+>+E)QK>&cOikV~0zsW4gQ zxxY_uGPA0_UUwC4{g>6fxy&I;is2w`3|@9)IMf^%Ik?mtf#0&Y3|zmjo5Nzb^IfDh zrgK+p1lm(pKjUsp%+?5`9&k4T=mK^6j9c6~K9cmE?QR5uce@(_bWsYx@NNX$7!EZD zhTaHJ4B7}#j9~Lsy%F$%Mqp?qmA6*9*Fpp?J5w&Za4mQF3uNJ&3xaZCUOhp5-Ss}E z+=c6(yx2)HD>fFSLiqxDIaYcjD3zOsYHINCPq5$Y!p*3=%t@>rrt{LB>UjjYMpP?a zNf-df1dI02DR%ra16Cbtmgl7|14A{rPZOY+2WaZD@||%G(S=)BV5&&E|B|6e`&t9W zeZS74@;PD@b7LeWFBZw*KQc8hj6;5a5#q&%NQU)HhhK`r(18dcu=%=A=&lR2 z`R*IMC@sxqxfZ>KM+P0h?jU;bKZUY6n6X)AUd;Dw_@JW?{t$CCl8ay@>_u~7jz-U& zIX|;knyeG1X$G5b=t5m>H0RxHG(RvI4B_UyLq-`5HOwQ8DcgMp<56Z`d+&iTPPL3% zINfdyU$`9yrlXCPE>&j=R{vlXN2X(pfu|;Ic32wUs32PF^@2qs@12>!@vq?cWCJmR zC7!V^kKVze3q%h)GxHou1ljXNioS$g^QXy30;Pj4Mgk~sfKo@{Wj6{eb>%?Ow_zy? zEhLH(Y`&@IH;dtz8x@?^>b-)o)ymqRp$tC~Y`P-3lj7Y;!T!vkV;jTCz4tQ=B$Qz{ zN-hk0p}ddbTONi%;9r*?oo?;98#Z#iH)!hIbUI17eSHWdqv ztS$oo4&)!};&LOcj4N0+V4sAx8ab*X1fbuCvcckhuvU7Zye}Kx9AwMJA6b=iG<+JZ z*Ur(#A)ByzZp^BlEqnCs1=aJjCW$U)UN$V(HGkd-OMN zHd@+EZzWo<#=)voka-Ks|2Ia?wZ%suyZ1KID_qt2rEvHJ0r^&+=1JR19}CjvMv1)K zuTEt>ATyw(M!s2V(Uh*g1#0Tj*>m-Pk*7F~v@9M2i}pXlcrh(?u1)Dwu9`zdmj~2A zp5KIn(uojPUhIhrpaLoQuz;YPJJKO zV6(4DbMMC(Dnl0A?>0i$amNQFlHXe*?+Rl#6ULtR2?GLh7X}36E({3xH(@Z)T!g_u za}fpu{h%;_BsXCMoA2t{WWu~_=LF4qdPrGpx(^yH^yS|Yy=N6QT%A+))%^> zkr}D|b-j3AZ2%S_1o$+5qLB?#I}6gIxB|SqYvX8}GGKjq_?}=)Bn~!!L|XY)BY)U$ z@lvl!dEwmo>RP-qZTkp^y0(gd%{h=!3i+)GokF z(|!o%dPEEAXa9ugB)!)B zpplMOVTAR1J|t8l97yiNSN3Yf`ge4>3~r?hjA`N1xfgK0anI9)gQS=K*~Dr6XKX&~ zAI~sJpEYvV%0t8}m8R&De#s;a0by-H(mhv>^_Fy!m!yGY$~KU6+T|jGm!#_+0ZIGS zJcO(>6oIrTGtwbdod9Bd8G9(Z7#WH{gr45GKhI`o(vN zNG@J^ps|FINoB-bNC=bkuq%>|;zmtECS_z&Sycj5ZQVlp(FWwG|3ZU6o?N*tNaC}0 z>GJ+B;Jc0rM$;#n(G++{5tF&luqp$3o+o6^tFY zm$ChQBl{1%7dF?>NRKwL36EBU9?cqKqEm^nCN9GPQ=a8^o+bkaM26703JkpcFl3$y#$9twY+3|U zrp@kA87$_vP3+yfUkZ%EGRnB@*4HgR!GrS)OqQW7pVzadUfqj_sur^Brkc3C2Sx~F zb4Xo5`Rz2EI9<@aA=Uy2NHUDnXn^$WX(NZ66;OA;uNv7i=j>kPDFmo3t5?ut&_OCd z=`)B$VHNa~r|4p!5LcjaB}`2g#zKHuPmQqw4Z~x1!+>1h{eFdLg{7Gt!1Z#*^$HVN zv~8?@NJUHuMjcvV;wJwL$KXND^_4DF4c2uCU6cf)>B}7$jWrk907MUfLv{o3st14r zg)~siiNx)XbFy9`qv}P>^Ewmv>6#x;y})2Y{E|01htzOqa1lqXnCvydy&=$}kdS_zjccRuj&1zk4Sy zjCEZiK=N-Q^+I`{Tp7v-mZCt8o?1wd0>x?yfS(*oTI$mU&Y^9WM! zg>a5?^Kc;X_lI+oFM>B>f6GubL~%$v@f>9`qHO(rq9Z#BPihs+qe;h$!#PTdf_N&r zp!Ph|r_8j@zwJKNX`MW>2oCc0GhPpvxGB@WfgybwY+SV|4!mBS+g?!0!Vyz-Mn}5g z4kXX^!&%GD-MRSZ2WLLBp$LegNoUId zuN39rcfji;LDAozU zE4n~vK(aRam_|OnTu+oLEdpMX9stQ8kd2BiMgk~sJ~i-|CShELf_T|c1VnL415vIN z1@Rb4u=y`g7u3aG^2-YRh$8-HCTt})iHQ0+Oy)G~N zHHOu5+A$v;O4r8SBtI=(s!6||hGV72Awa<{T0P+*xxRUplekGV4+*bsDoWSS0R>1z zMgs7Hi~-7XL_s{LG%O*V1QPN_$w~;=6&brvaF9TGK|B>1XDIDcp6;euW&Kn6L39oM zAHA4OAR`deQPC5t|sZmv-vVC%?On4kXjheRyq*p}2?}C6^Uz zFO=NZ#)8eSeAxL_6Y$DLk-)G68OBlMD>jOJ&G>$!^9?)nJ6Tt+FRVkrzpdo4xHyV* zxCb(No;{2IUMRV9>u2`nfDJqJW%k#)++obPz~ouUTVNV8-UmjM<9yr;?SAa!3ydNS zf7*EK$nI%qHE4p5rAs7lx0b6Hjo(~N^r2(_Nj}`wF0kFSArE|*e|FyA4*7XXVY{+p zVk)opPA-h6-GHQ55%@B#UD^gXYFDI(L!ND3Dk|fTSz*)TPF@_I0ZI1;6=9WYUG_NV+bj&PV3QzJ8*S zQ<6U4%*#byM2Si#$1OM)0WOBZOEm;i$OR`xPxY_jkmo#JAS$yWN($;sGF>Mbc>ao$ z+-ZK*DOLWXr9)mf-6kqQzZ8TO5pXe-LfzAxWI^m|LE55$8b2@hC4Aw!bULr1OJ_H9 zCr^H;DB7jC(XfEC^}D*FVyn_NUA?}uu1?~~sKe;O+LO?*7vl`Lr!FN0zgiu)K95hE%T8n`W zbyVa`oy6I`x}5|&O4_B-KSpYD)!@HGWpTf&aLjvHC@L?Y+$&kog(NO1V@Wxi+{5^h zT`^pn#;do!yNksOBzFn}2Md~*oKp1fyBzYJ->W0*qr6!!WUPiIyPa{p!-spbcM?x# z)SqZq23mSJ)aU>>H|%GIfZ|jA?8LPvz%FeYm&(h>213(fSn#*Q-LwG7-0dsvOXwxZk;3~dXJr)bWMbhRF=bMp!J4r7nH=qk(zox@GqU+xOvs=gp4WU zl2EiVidN|e;#TW{xEU||{_zpX{L7=j#0?aXoDT{}sd;&qLp^;51V!1^E`bG_O^-E~ zL{3eEF`)CVpqMY(H1+E4)jBVo+E>#^ft39&*01g^x=|lYtjgC!M~Poj)J6O+>~Kj7 z$7<s3X;X!MKjR3`lU?d!%dg2h%7%!_v0fEno_qCzPO_--9Vc0sFU>At zyCh?~r0k8K$g4$mLlZ)INtt)sNgfZ~YnQOmk+IQHO24mEjl~oC|;27 z{2i#T1q2K==qRBBKM{ync)wj*S`5x3)>#SPJ4|kE)YMA@TkE{sJ3Nsm>tZL`r3Oc> zf;{;Qzr-nT3;op+g@IMeUmm$qkTg&e;cEeOUqkpc zho20;_VDWrzkcvbf!|m>GCc(!^n7(Hy6E}pE$G^9tYmL5TB*s^~=XH^YNr@1|tzB(QzbVDq(mG2mW^?yXBg(SH}ZX-pC^7td=C zG1MFi%Y!5Wj-z`RBM~FAUMOqssMJ;ui5Q8*7!?j&)QoMw{&fQ9A|tv<#5l|*62L&Q zW^55k1WppM(H#@^f=R@DWI>k(iCBPdm|GE;eBDxZ!7Jt#P5x~Y1Cf6e*iV(V?E@#+ zE^LrFt8_XzYl2g}VnJVw`m%Hxq-_Mwmet3jvn4pkUyZZjxp~}luDc1d>|GXFq7Dbz zv{bjK;YAlTCanv)95{7B$AVLrb1QJ_V#X5u?~rnKVPumzrWSC13^I?JQK>!e){IK+ zNASRW_99>s&LR5j5{AsNJDT{fQpv8x-s%PQkeyqv zI~b(*UzGdo`ORLzK9tGqY`<4d|6>~Bo%`IsWiV5#m0-{aEmcBaW@8Stbc8mK49xlw zeAv)zVArla`VR1irDpu9p-ODtR~=5<15#ol-8PMw1^WYFz}EVvXz^GuOP}3>{V3Br z7VIghu~DS8R<6<=qdh} z+p-5MN1hb_&)BjD%R@B9cW)^8&oW`3WhLl8%Y;2x8=@bCq3QkqOcVBCzsQq=|0EOk zU>wQA_kWTJdoZ2k;rlqiX~G_C7SS9)O9|_{|F4*?2RlIj38w485D<)? z;ADw!zCLU`rGErk+pr9b6s}l=pKy9#yfemVDVW*IZhdiN8IEIeyLo4<(fzHb0WBo@ z>%ed@J)3`CFiP1qF*&)%0JxmSQhL-LhqXr6mGF_4Zku<4(b9kI*P>M`N)Px=WQW%# z8M$+9;e2YxN~Z+ndfs@jZ4;S-yFCz)v`k1R`Fz$0k|M%KOk+0p&;xpgPXto{#o)^+ zey~YXt-mUIK)HIOG*b35?C!QN1PdT-YqsT;*LQn4)OO%vpou4MI>@1<6Pon=54$Eu zKJUaUYhE9SQEP*Xk-T}*$wrE8UjYYolMR|YYm6IyOM^)QG5^p?P=?3M;MG>7u^uD9 zIYuB`Q($j8esT&dNL_8hEAiFx3F=vJF;Gt~rN9T1cFT*7$+$HR){y#bD3R$cqzz`P z-P*s1h)XwfnULlgxzek8YUJ_+Slv_dfRGCI`wDR(Ab!qXjpR=o4cp>Di+Q=7a|9fj z3;YYR3@%1eW5pVc6jyig(#G}01ld-=9pDq~E0DV1q-sih-Ux?U;t}i|QPA&ZY!XQ1 zrkR@LJH3D=hjMFqrM-U#UM&wUM&iGIl|Zgq=R2gCrRz9k%TssU3KjEcq>;D+)*)vV z6VyDXg7g@kEJ$j|*n0AcWC)-}mYSqI%qD^UBTmDWA(n8Iz}HLy%iv4=)LsI)ody!< zX8;LY8)rpa2&ma0Kp>Upt`MYg?IU^lyXJvcy7Q$Ba7oxsIF^RD;R$nPCeVb>Gl$}K!`jT6@hq({I`Ug>hb z7OXQVRG0vI>cn1wiz7CXSG#>S+PyaG$WyoxRc>dAtXGTN`6yyVGn-B{DRIuQP& zzsvgft{{}a1}1@x@X5rFaT+-s2g{WAUpCUz2V;{E7XtnX1*3?|&#V`uKR%ku%X=sF zrhM8qDET)bWhM! zfrO^)(WH`9%V=^&z_+~eWO^z1%mZ8ubo(Q8S{B|KxohUBs^yfwu9!^A1aW&XNC*XnJdd|a@mvgU^WDZm)C1#@2z2Qd}TJQ zk4Inn6mtOqzc>61J_Wzh#vyI9!7j|-j}v*t=Q`}d`~xmV()5=fHS)dGQj<MMH|&>C|dJB8jYgSm~uFcT){tQ zYb2vDhz8GU$>A5_-1&=ucuk$#c0MKuBx}Y&MrWu-L28(H2QQcFm&z-B3;*g+(Zxsx z{R5gb?NyjVIuTJzkXvqW$9?P=B#`jyNt#kn+K{deZrNUsQG3@RI2?VTH5l&shiLNY z>!0z8Q~8)z&wz`8CR~M#HvN03L+VrW8;86&4y4!U;SF9z7bBVb)kZKW7TkuH5Q|@%tEckog44&}{zM$oY;hWhVv$hZbPq)nEvtuTIaa z3q$o+Af~Ulkpxz3GJk?@7feaTc27)78iE{!P0CES{y8tq1st72j&_N_(JrJ1doq>l z|BCcJQosH{Y&D5iEYAz9JTJm$LWbUUGWqjXqSB=koXq<);&)u~hJYVC+rfnJ{l}s- zHS&47+~wA7K`CCWvY;N*n(8Ed*O#!9R{t37Qsdge(ekv-?ts~AOSou&a`-_bLA`jM zZruQAl>%T+%V+T~qSU`-LtY;IYPF#3KMSWXkF;Eb6$?o2EKpsfafef)G#<)S=G6^g^=?unUc`hL~ei#~0m|fiKf}&!o9BAETTehh+x^cl27qpw{Yp0taCGsfdfcc{5?E0+oAk2>(H%PI zyC;2bRYC=WbnjlO`4VZ;KzBA=mk1? zXJz#f z+rMaxTj`IOn*WJ*8Ov4$3=WvUkmM;?6fY<$rzo(P8F<|L-dWkb|*tEqp zUWxu2bR@2PIl)jCNlG2h&y%e`E6x@j7q4=(96SFX{*!?n{^D6^zcjE>T&dJDXN#@V zDmz+UifJc&;*XoGG_}*mJ{L*m@qJDZAy__-iEEV!H`ZiXJ`Xm7@p3vNDQL#+od3D| zpkM$Zb6 zX4qhI8=L`|8o(}1K`=%`#mg3;*=0y1VgeGfmy)rt9uI5&bz#k)?zPYj5qL>U{lW?U zY_*;`k)+f(7{rqZV8%_is(+Fl=pdyAtNK?)C!tPIGZFzA$-3?e{2{a=gz5>oue*9D zfJ8usv-pE;7l?*CF4_2lJB*M&+?3IsKms0hz@uwdXg^5=NH8mPxOWLcYiGf@Q-3GG zbD0FtlZf*O!EE?I8;v3bDYVg@Hs;I(Iw+^Cq<{pHvgb@HM*!GC0xIkqAOeKCofwz; zx}{8e4o0Fok%T%)L?$K5bQxwWHUT>4hHKCL8zk74O#txuc;g z48_d{y%=KPwQJY>v3dyIyzpEt_AV3<>vRe1HZkPQE4laJ8%BEY>5fN^>(@eK!$5iI zO>CjDkO(?6LAwE(Idk8?@n^S=h2uVrk?!5l>&ECE6?7Aa-a2MtdpY1?put!2!A6hK z*V43K0^aXix@lscetltUrx9-LGy;QFTG6-wgW;Cz0qg*^_chaSxPNTM=s9o;M2$)I zgT?^E=VrM2*kCBmuRF!_;s$3i-oEEXejYp)9Lr-9wlvAhi_<&&WU~j%gNYRAvectb zVsE%Dt#o)@-Dnx^_8vAGB!d)NXb14`(Hkn{JoK55=?iXS7ju_t$=Fof#ip81ZxNv? zg(RE6pOrF%fAxckg<1@56Y**A;QBah3roX`Z-Z7o%kc$waa}v+qLTvZ?(GP^tn3{p z+#T{k17LKA%*J-lpbtd@V66vs?wmLP_sP1VFnfV8g(i5d+bgjCg%$|{lM;LM9R$~d zfQc`C^{1X`mdiTwr4MeF0U@PidSxa zw3SyszWEo96)1*4e%uY;;$0dVtI16^0|sfnEk?DuvM@w)sd{58x>AO$sS<9SRuA9rqW zaVOa{<rzZ3rYa3Z>D%ETS9{GEL3y+nZy%ga4^-T&~QlOlP0c9ByF2Y+?vDSD7H1gu$}bC897lLV>z z4#)}mEB;v81y1V}|9thMlT?}Da7q}HQczx`&VDZB*r|jd;=@dOTZLCHrA@EOYVwM8 z0?vKlu51{n;P4O1vnX7`&@$*dociFsC4O)l$=0Nb>7?%V3|^Wr7;+XravZOGUiiBh zb#=#aDDyHL1`;5%NuzDR2c;PJ+dfAY1qLF9L&BIc##9hZMOrt812NJijL9evjZx71 zwRM|fCd=0N&7!qV)L!Hg??J(vN%lW?b6GJ3xTGlzy$ABwQ>e(DU+LyDvJ`On#c<%k zo6Cya(myNcTw+X?4@7h4qawHXK!(m`#C713<`mIXL<3pEo!lNS4JHZhGkIXbx>22S z8J4Roy}1ngS6Nbw99(+Kl45*NmT-@E7MHU>b65>|3!r71NXlhxZonPT$TQ7KJCzQo zKQ*g%!rE7x%UFBDL4JPGT9m?ffqc+kAy~&f6fG^Fkp;JOb4s&NBTH0-nBEs{L+wir z;jN#iU&FGCrs;jmEqs*EMN-lgQF(a_wC0~-v}S;RUsy4|L>`YXk^K$&_d z-b!#_w@i&iqEzZOl!xyKhzS>f7KMhDct1G1#tb#+JfE5BPRc z2bhwc)d4Ab=mFnOQh+H1(^YA@aH)tf^!fAWxW(YpdSGA3CJZoRt%i}&n9XK^^Of#4 zOV}eY9AhvvMO}0o<(l6L+N0=Fv+!U!tlzfU)fHQ^7ToeWa5#I`LpVTbt~TBwKg!pN z`TrW37e3@zbIz_z&oslCd}SQ-A80DN2bN*3>!ylQ(pCMGX~8WjqbL!d7rt15n9|8d z<9PW+b3LYLKjx$L4nm!2Ej-^|8O66Dorrhc0nR*ZRY5jVS^wSUlX<6O5OYug>x`^abQK zw%RIvVdsk&yZ$L^^wk+m(vF8v0y98VQjcDBG?Ko(Sr#3ND)1992yFmj4`FIdHl32Irggonm_honoD{1cpNOe{Gq2rYf70? zZXPec1bw84p?)IE#qrC*u)wz-D86h~2R_Pl=kAY(lkKRFE@fu9aWIZ?OJn(qS#Zf| zm|Ko0J%%{$zOIi6qnAPL906sqbc|J#JA_n+ou-{Vd9_w=T^}b#z>)S9&nCO13bWTb zOftyxOCu8)`QLka8zQAvE|aW>i0BJ4O1C3bfWw0;@e>u9R6 zj;@cxo9nG2YkN>1p+}htJtnSL!wo*h(D3kZJiv@+eFNYZ3_rJV=<48(gkLoL?C`?_ z%mz4(teb9z=?+eS+?S8zT)u19uHN@odwIEM++~1DUq@)}6&WV?%scDyYmXO+z?rT) z89YGwPBLCz?qtwQUs%BNx47h!eFnFQUBT(e0HZD$TiFfIX2of#u(Mk-b`H*{XsRV+ z528CFVgUL-_wwIl%1YDg-tGTAkR$@71zCYKT)V*dDohnIy>8KG(MUB4hz5dx6G~DO z7l8D;CF$Lpu3a_Vv0z$A?@G^R3|e5*Kp&V{)46yg)P%l0`Xt~yFB>5ZrPFeH*`$Hq zD5*~(O)!Nt$Mx$w5HFAHkN1Kn!@b~!5wS2E-ye&!aX249!)to3Qp_VJC3otVkc49z zg8}ZrxjE;F2z0tBX!u&vV;0}XvUK|x!8)LZfZrke(gBZ|OS*GWBYhj2or*nhNxE86 zT#rqJnd@;3_EP`$_tT_}tutW%5d4*ZW6Sw0iXRG$agYHQ;2yMCh{-6>l|_+-fiW2c zqGeHdQkO7wN&yvXnQoHMi}yg`2m$+-)mqrB^COaCAOr53!`DU=5zOo=x{bb#$SCec zs2f;TEZmN_^J^0%WA#|4fN_q80s@^L3|>Zm#Biuc3*yMa&N<;5ZWT$DCxp2h!C#z^>DC97WEx3g`I>`6rYSeX;bpN zF=*;<_X4pu3E`v`AsR{T9Tg*m4y-E3ZR+X%;~KyxVK)+gb0`68NdRl|Mht0UvpKkM&2ALl&&mF1$&_19Hlug z$#uF|K_jIf9|WUNZ~ft8IPh26mm3ZHy>5zDUoLi#b)Uiv6JyHXy8Xjf1;Y`MI56#& zdBMV~9)Ca-$gV~gcnNVBqU{%dL2a;hH|BLkE_p3+rGsc4^D}&Ymo@LCrM%fw$~Rdl zSM)07YFNt6J*BLdNkvx5ySlwo$`v_U$~Uo;&tNJ4%F2);!g&UJ&QjL(h9bgl{JW)G zk)x$N0ZaKSEaebZ$`x5DJ3XZw!%BH&E;+CH={(W8EBYSlxBG6+lc?W0avs5Q?n3>} zJ?9ZD=WE{8?+C7LuKG<8b^XSAB4d8D={H3LqhasnJc8wX6XyI&%y|&Yc?8S(op*D- zDwmwcgCY7>e8#KwcHO`l zX5%E~CF7m7iwEAELv3H3OV0OqyUbgQeho9~Aaf&Hv*Wp6?a=&}tz{EfPIP|aIa~T^ z2ia2n7hc+gIq~?9zdR+Kd}6g~+42?7U9pehiSbyZmX$9h&MPPJTueHcbL`atYCO%! z5SH_JZqnr`Hj*@`u%LM7E1v6@80H{fo&&p!*h0%r$QNsK0+SzMDR}WNeTt=%j-?Z9 zUXx4CALNbMYb|i~F0P5Rra70mf+nyaLUzNNTBhxZLtV0|D56T-+P}cR$jn1dspYFR zFjw!DFGg9j4D3DHt1rY-mbksK`JE(a)>fxfWz0DE@V)plUMVpqT2t%H{e@ACy8Rh^ zkGOV=Qz{w>9b(I(zw=6)UXg-Yq`*e(i6m~|)s;^2sBdwnB-DkG^S&m~SB-B|UQpYo z>lmjyIpF4BUrm#)-kAc2SE2ypRW%<$?HHhAJpLN&%0=}4U686K!1%wd9Wc~NXoS_x z$C;f=o#f_uFf>%=GwA+XARp%rLHF zm2IN**|5qQc7rG*}F776v=Zo`b(zXS#CA;sydSMcfx85eGV@aD?%s50opq zpj^9h3Ex?rWZXosbDjHOsVn#0#wuXRaZ+`-HW6Yn3_57@V2tWl2<}22H81x;Td;X8 zXgC@-^YOLD_UqFLwqv?fYu!DeeKyZ_YV^wy9toRk&qUTm$RF zrKJuL$+Q+n^z$KpOXBpS9L_wcmM9@*Sy;2FS@SZ z2M!y+I@j^PSEaL=nHQvuGKOnZErSC?#AiB-%idyIviPvKmlJM)9cp$a8*+gMfhY}MDA z&;?NkLGq=Yq^q^IjYZWdKt^r~Qtv`pw9^3J3DZD2M05vYbkP%?XB2dpNhyNO>)fWe zec3QSJeOhqFgDCbIeLxlhX-o2jW9mmd|{upSkg!wfqg|wa|9cE=IEP8{OhP>#Ct|1 zBi=JAp@<(Gl~BZ7MkOQOGb$PJo>9qqy`A>Va)x_JViMRY#c2-L{c<`;VKO_kH3d#A z-^p#F0|8mHl-y@JK=N->oopz%S6^=qvQ2h20@k05xDGx}T&Uxri9tg;N;=@2cIP+nk zxlDZ^AosZs1mr&X*_dOX05YJnpUr*SV%=NGWUvbEgZr2H50K&|&P@h%LNxA;h7+P)Oa?y~x!k8j5I|+{fjJS7 zP#NTy6hT1lvmyri!D$f#&1GH$0aOM#CPolIWsqZLv?Vtg(5aD9us!O*ekOwhp!~T` zjvyfS*%1WfK0Shff14ixN$wLQ2*`bg#6UkdMFNuC=Sbh=CIdQ2dRsFMWpIMY;Ai7| zrb!Tx`#cE(a-S$cz`xCufF$>+5(MNvSAu|ln=Ao|XQr2JwzM@j88q0t`D5$l&*95~ zAUN4e+k;C+PPQJ`NYkggvrm{H;Ew5pM&b|edEbl)NPayGQzrY7)$f}!0m+J99l((G zb+{)s_c;@gj4!*&Nm^g`d*7r9NN%i#S<~{nbN?HA?*U##)%A;~odAIxAOx791Q0?~ zY6PStGn3GfK1DFENbiIyRX}7j`fK?I};NXeNAMG#O?s-l31f)r7th?M(Vd(WJl zn3M2+-~YYe|K8^&&vPbwX0N^WT5GRe)@~~^s|g^1S70`Mav-OYiP;2@D}TXm8r`*h zW_A-mRz*KD#Q`N&Wo9@5Wc8~!EA`c?{h3)#0I4-MLJ@zvxFR#t2_R2nU^|_>zbrG` z2_QQ{VLZJq{*jsS1dx2wU_E^_7JE zG_}<2DYM{Ttx{!0AGZaU_PlB0-WLXv_eB?M+$z`&bgSfhlJ@bGU9x`UDP|U~r+h&s z3$RQG3{=FIreNZLOfv2EDohVC%VF+=%{G>f@2``^rg>18Uj4SRr1cJM5UVeEh?!H{ zQU;dhHN&ta?3eYH`o{R-_S8Z5+}JW@PaOax$ImJ}H*Z*DsY9m?O5wKh=pSp#M&BFk zCRc#GylB57-j2k9n^H+w)^%4dspuzN6XT4%rCz2@VO!BK_%|}A2BKN`n>P!O1F=!y zjy<+yb{w;nMpf%grq<&?;r*)R6j2SkY^iTGh0EBND!w7>Cy(TkjfK)W8|3sr80Bl0 zy=JMkJGo44^Sbr2p78o)$tXBxk`1ywa4z;$l>O3FYjwkZi+Zca%X*)eKZ!Ngt*c{$ z7+rrtMqd@M)NNrEWNnhwPS&6NjeDxy}`=)$jo8|A2ydLwKQv$ zLTRFy7z9y3A=zvdGaK0qxotL13<3(6orsk(F*_N8@qn-`O^~>+?X`?kx;!Wo+Y1qC zLva5~P5|+5dm+NV?ZuI1X?t;`erzv9__w_f;otV!kzv>Y8Ti^>>$nVXmHP8+FM#;B zy%6Ew_Cmz-Y%hTLx4jVI-}d52v$VZF@xyf9QRi2B!e<*iETp5mJrVNO9o-zQ$zYGxJUj`g$ zmNMW-{m1|j{$+p&|1#L^PX@l$_}5$p-vni1jU(cD);K_z3^G{bi12TXbEH{X;~c3U zYa9_w1{thzL@*g-u*N_2Cj(z={Ch5gAJ827wZ;+Q-x^1Re`_2O&$Gq>;@=uagnw(C zBhAtp2Z(=be2+gF_*&y>H>o$QP?awY@^uA!xfZvV`>}D;t!o0rzrl_O{{}lEo@cNF z#J|Cg2>%8z7$r;{ag`m|0lk0AVYb zSyzG+s;{ag`nORul z0AVYcSyt?>+tnE+v{nN^DP%V3R%K5arK4?x&* zCTWS9^XfbMv|N|JrsYgqizWpN+c(4Xy^@Gr46o^H7F_Hx#$K33C;-y%vpkB}e9Ur7 z-O?>7MSIp0mtSk2;ev2`br&G3Hm$df*7<54i7)T^8m$1Sv;}*6voKl#@=J%TjaGoT zBH`b+@U98IM(bBzqt(mU%wWD!OVbSL)@KpH7HG4WTmT4Lq0M4)0U&INHq*(4P?s+S zX%ii&;rmd-{hQS@gHST_`N^;a!G6tZW^m&Am|!wTZBy1UMOKCGRWqDdMNc@?y zcJ@ms`%F#QC6s;ErYu8{sVU15WNFIow@o^J7@Rib7RRp~e%0}d#ji1bZSm_a-35;OUD9H0lzEk|N96OX?GS&~_F=kGFltfR+PdhDaeXY}}*9^cc0 z-4cA4Li2->F#Q(VVRh-m<0x!B#jacIHZAY$p>2iF(`jcd+l}jdE$3{HWv5^PLI)k4 z{kk|_3=DM1E!(yGoO6rm_o@carc-_d^uWE=@i_;?j-*YeulQ~{&BfyRoB$>P%vUf8 zF!mKp0_12rylbA+l&(Yyu%vSk!B>DSrCxZd0#4 zLNblVE5^~hSg24b_b;Y+dE-9Zh4kj^{o0tOBPIR1yjwErUG)wc3&BAKPMD5b0>ZrbkAK99d8>rID#7?+0Q!+l?wghN)J%>h#k$E2!7 z;?m*ZxvT94{va_NAi278@-Za5*}P(k`?|iL7Oe_0k_!p$ySpXv?l@egLsN@dxu&nO zNk++_5J)Q|5(J;7vLmsP(}|?y9&d8Vo804tpyVDtNyU=Wd>4<5aK%IijMzm74@1KD zuNkAbU)X=r1Zl+>X~l(7&mpb2uyb{Rnpx4uaAZke8jj3}d^wHC`6s`V-Cr7osK`q* zBFhK@5jpsD;mqV$21L%Q;X`BvF5xsGG8`T+4nIOn!;yhV!iGY|{Rp-s-4lB5pia9Y zqwhr_8C8@Ds1`5Zt-p1*uSB5`%J)TKq329>aT&mPA#dRjppQZf0yr!$4oP!xc#I4< z?5Qh;gOxPH5#g%Ik55FpTxb}>@hga5G5kv7S205?8HBd37}`2^g28DG`9%OG9U`cQ zR`0~|n$dLkfD=S> z`x-km8J$3B0-_B{Q_vrgua~SK+eGFaI)JVqNO!n_`0xR#Sr5CU*ewP4PBoPJ1q7?M z%}GIGH6Q>%=NbxDf9-1#=H&NyK>|DgaZWT)s<~mf23?FPjnDrHIXWa#C9p|kL5D6@ zFF0K+D8{^ioFVuBl0Yl`m(x6_<74++2k|2s{J_4eRnHM4I_9{)ej=T=n1YV)(${qN zfpgj-oW(aB(x(sa{M_G7nJlI6_i9`WiFd#CS18@km_@%gcBj+t~gT#=R9(T51i8nhj#-;?ev+C z&lRqHbk5@*@p21lrkq3h3!{h2;>#NayBS!XoXcL(pb#o~ZsFyPi+7420*p5UD>ww2 z0WSn_m|h%`=HS3)*ni@%Hw!Wd)(j9fG*ioiqH|T8M_Un{fk3Xj7jHgF316KfRdEmR z_%SUZ=VvWfgpgdjtjrs&70FZWPH8zppf*CF7ESyz`Y*d@dS~e_f&jJS5MmHWPGn%* zN{RTw86irS+-^@P5kG%Nh(PEH``XS7gg)9`!E&!JH%9@X0wYuuJedlz=#h$1vb%rcr=$cW7@;MF36PgqB*^LO88VWPVbf9) zeE}SPGQm?O+Iw7b5UVXYhQs5@GKAAj!5Y zBe|ULA(5OmJaMv{wsnQ+Eh}t>!*>k83Y!Ky4#{aaY?7J6Fp?SDIQWto z$-f=kX1QN|y0jihuEa>L{9KYN3+2wDs-=-^>t~vj8ICMTPQ#Hw%B+gu{7OcW!vpKo zwA}5Rx1>SV%Z%C@g3~bUq8fq?v%D(Tpyr@vR?PuR$(jQ;^6}Fgq~Y+26^)K9R@UhF zh~UF{>O!>;jJ$W+w>?! z44-J2YQA4erDzNAUGMdKoNQ2tK?JVG&XE4I4@oMe)L2RvQr4i;TkZ1Ak#J8*eZf=y z9gkS3dlKDYQeSY*50}L@(^~Mi#$i88V&9F$IHYU7O$ln_+MwvOH!=Q6v(0ja|N47= z%Y9}acEJa`T7-X74q8*V{&3=@C3tbUS_wJ6UA$lXY+i`!s>P}(?$`5-rN*Q^ zqxyBB#>el-V$$qG9;AF-Xgd_A=~DB~;cs)=y(5wIOcpn6WVk7|p4NiD4L^U?Blg=^ zjCgom@JybGjZHfmrs#ity+d-!@pU2m`d@KWjwKsV3oQy~ymy#OyRMAtZUPBb?9wBIXz3=9V8xu5NAtH^5Ug0F%MGHen?QmUBj0Oh zrjuPafdngFKO5~MJ3V|~Ny(9JH-Q8zrXD>hsU&qry4?gSVsX>&D`HvRjFNt}Knb?3 zJ5;B2<>BiatiW~BUsfcU_h-}(5YBc#DN(r*y#s{l7Z%5gJ0Aq_HvvqECB}E*Z^V>X zbYMR!j{yQPCE|Kf>aPa~#1!d`tmpNidw@VpiDyS#_n})S4RSaeAP`e5f0a^l&LUhN z`k_A0TWfKvObgaJjs*3gu2DkMzqfnD_gdhl-GJeX;*2uyv36^eu>XfdSbz-g<8~ZOs`a{B@!md}SRDFx5LfPT>;dqSL(JO>uLzk5csh_r^=c z_A7mfLp!HwTeeDS8L_6RjgiMvU%A0g+fsPVT+>~oUlV6g>Z^K{5 z)xWhD#A)5tXZ7^GC2N{SX-+dhhNxi>@Hy3^mj2gj4=1|l?c0(M$nQli#EGHbjFr_f zH9-aAt3;bAamH^r*91C&rSrH@N!$fZR#)`^2xY`0at*Ey_ttk`GxfRqtK;6Ml6mQT z)kl6fh+Q|{<9>g1F4B|foP!yGLcwpom&A!jTTA+-7)WwalUpPiL^K#Qe!uvze;-qA zF*!uiUjO`x9kF3_epB3EyNj&%eKs%F_->vP!BA~>wU*Qo7f?JetplnE*G5026nNar za$mZ7mAb^V?e>$aFE_=xNo_5CbqTnrYky$@HN@B+KQOqVCC>V7qDPHx2oY|ay;9ca zoQDW0#6jM!+tQ-6iaKlCPq-A}G}5{#ZHdMm6miVnAMDqlW_BK+Y*SElWc54g#>L?; z1@%_kkB(oZVqU_9v@}pyS*oxi)(Nd+>Aoe0hg~&+{3BLC zli*S_P&js8KmnC_$x;VE^|Vh&^;{GY*P??(l$jiETikM)aiITTCg9$3&OP8J=W3`B z_mWCHbM8qF4)*|Aroby9Nlq=-7k4)^?pfxWKEy7Xd=DF1I@Jeb3$G7ERV8pVETWF3 z7Ra;8qrI_g79B|3>_;MHe%xldOWhno9nl9|BI^Q$FBC%&>w4;0x*399ZNm<{K$8|c z!V*85zSUHJJ6g}9&8o|;5k|yXW0Ncn$kB_g_i_*nKUR-4FsK@=rw(i=W0RI%;jW-qofS<1}wE08%z7K@n%P07zPk z;lf-yv5N`Io^34@7=N|IDj)w~>YqOTP%=VaMuD-2kEy@_r>K=%!R6?8M_3Uf#oG-_ zDB{;&p7-eUUAV*}Ez4It;Ar6w7d&aLAtbWZk3=p69hcod?z}(}VVl@pu7gm@lbu0I zlXEE`0I&N7zGaDB#rCpZxbeGj#&;v@5M?|9lDnK_s;fOH7eT9RM;zG-Z;A;+Pn$Xw zn8B2frSM`_557GoPP=#*yhOOR1w}9aj9t3#HH^boRm9|aP((0Mc8r(RaojdNd7~_T zS74x}{+)md_W7cZsNF$Cd_IpP&Y0EN(#xaf89KE)ETZGeUWj-Y6{`-Hp^%M+q0O32 zZPq5=$wa^s&_MVg5mg9?L@yXL< zN&V$JXvUgT*uMH@0yKj{U}(D^hEi~ZmPBoVp;N?=%XONG8ZBBAcrXm5SBP2>yNK;^ zV)$pYUbd)tge8u@oFuCkE3H{sBjSrmrEy(a zh^(kz^o4qEf17CsPXQ&^7o_Npgx)Avb20&$et>|L;$myLtQ>t{Li;A5HAIe&B|sqc4e@) zZwH1iyqV8*pXqyq7F-^179Iu)G+q_^d7{%BL5QGXvUqIqNsqeDv4T)X5P@O1DSmNd z>3;r-akwd7Zy7=(3B(q`m|2{8WVHQCgJ!XG%nj=G5jz;8W^wT(>~AKd&cGNEjEv5A zqD|H9Gcw+tVPp(GimaF+yX!8)EOb8CIKHQ3e2@@xb&({td@qlw@1cRF-6tU8==ENv zSmEH&I6lz)l}5)ud!SQSYcUrD02x`hJB}NtyezBrKlsz5HTa`Bk&B4l_sLzv9L(6Y zEqTskj0(bpKa23@rXJ{n0nVVwnEsD&eVSoR2XgOC{>$TD+4dgICQjqzP7e|a?x`$` zCotO3DNDo75)lQiRYdo)_>!y=ks1-HFZJo=022A*9a(I@ai**itGt&>*a3^+N(GP+ z>H^5qYGo8rfAhYqwgKVVNKQB+*Z?K|;~!-G@e9{HPPc}L-PCsvM)#+7eX=}`cWW*} zg%lP=&;SLmjPS5Jg{h6$lc5U(zXcYKmEBeAHKsxA0^-*N7Yo9d(|?o23uu-=A6^fX ztBHf$W2)g+`D?$x={aw{5b^b-(iXv4YR`NiV;gV2cnV9by$@c(i9W;bc6~9c#F552 zYV1a`t2e(DD?b)?1pG?iR~ElY_`Qr@J^T{zYl&Zb{JP@TAHR|Kji>eY>GYUOk0tc@ zfF5jdeiwz<;`}iRoubDDdi+F>-{^sRwj-gScub=QeB7pAfA7N9-*3}0I=}WCS1!>a zOC>CqEJ=Qsg8W);e0A0}x^)|2*&rv5qoLv;F)<_my}N?#h4%n<{c?si_uX;pv)A0c z>-O1e?%8YZuTra?z2;8q_W$#1?*AKC%Kv8;ga7|r?*7khSolAFSHW}E+}S1h={mkV zj^6rTIL1Eho!DoR> zlCP8Jf&acM0^iMaIoW2q|CHl_Rc~)kb3Ab1lIb`eAU-gDV2%guaGK)*el@7=8=*Y; zMo<%a`g2E6cUoYs_@tyhT|4$GS?!|vL!kx&dDsUE-FEXIihwv4K2a=WL$*Q=@4x*ixgEu$oC=Ch3CXE1W z(ilc(C5O>1JuY=%$DV^-kxa6AX>m0l$v8hf!mAEzsJPGMX-H;0?Zk7r3eitkIpVM) z(gXRFqkQ1<%vFx%gDldJ0$&q3yjwS5p$D)OWmt*yg)chQz)Q- zt3+9l@XQGWlw(^D( zj$yAQYPoHNQz}^4YAEZs(LUW*-m) z`8sIixlmTVF&62V3#28<$#iY&i)`Z*=Drz{Ok$kPv~Zo2J_$K>A%98%0msQIAY>Tw z+xh-8hLt$yh0;)2^E9BW9P+Oc5C#0aZ-S4YgaQB}5hI9OcL6Y%e*}n#H?~&|VQ)9U zSzwTyU@@iuz71q(Ih~suU5>*i=79)AgY9(RkpW}oP3L=s#3b_2k~gim5(Xv>8iZW` zyG20T=dvzmY`b&HIZY}|1fUr0mhb*%Ur9uhlwMI%ZZh<*zZZwC#-f5Sdl3e1SOFSxcKAocF>zE*9%HHG7{SoI6c&C`&Ke4UT?uTFN`DS z#my=aS}_ahY{g)l2D4`v@G})jtA@~rs075~I}7@NI5iUAOVkSY7Be-P{t7uNfd(gS zcE9lt64QMLwG7Oz|5OZ4olMtgrqc&5vTh4q9&nXaCHA(moX>v{l2-a46m(FL*b=3- zlwRjwok(pdsrN7pG(a09%3@Z&Kh=rxX-kP?8vofq$2~hpoJbBry$uM7mYR+<{qv(^ zd65_GLQC;Ro3CaXaBCvrxTMwC!7`-<;v6!SXtqtkg05`Dzn07 zg-qghDork5C8ESWRWvGrG$&*K>GS=04R@y5@GZmX1xR}1Q{{O!tY1ynBd7cBQ&pl8 z+&-$u`b`eXdQ+$CW+k2OyR&6=&zuHtrh?rQ9%J826Aw`ggGyS zi$Jr^0MWr52jx$pFyD-rK^wxnCOGr~C!lh9p*X$pe8lKKaeM}g54PXCbqlqZt)qtsH(U2H#X~J_(xz29)^!u#UC#Gu%g>SB%%EhEz1eAGmWFSZ zXKCm=@*rC~z@7nMd2k9`I5)s@YI*Y@+4c5YYICvl#K8x4>|lF(~FzpD_g&#by(0Jcis0pD7H^8jEt;I z^9H$vKc+AD5RG)q755>XD3tbHV&D13W1sKE8Rs(Lmoy(d_)ht98F=#roid|Stxz#c z*2*5U>B&9(HJS0He^_Uv#~41!<_l5*JmkRfGdbAOB6vv4DZ?T-9viTZ5CZE4ulrhTUw8EoG6es?h1rz03frXM!{ETxAqO6mAd`)>2kFglc$;*=6{ zenuq8m-vSI@9E@9=HcH7$ zgRo&@qyhI=7!;Dnu0gg}O+JV9r0iH6l$r3+F4Ur&tQJ*D>gOsKKD|#xsz~L1DpGkA zLIup5gt{u?oW_}LP!vpJ5iwfTVk_+X<0-@-nvTou5sx$~!A?Vaw0XsSzgN$Z)4n-- zuJfH?ytn+Ry>FahWQ_V^ltfC&3&EQbIY}%h&Nj=*p|qM%xy5Qz98xlmrIu(}V4s$F zwnm&jWfa_gFRt+|?a{0zbgzSjUNZIW$*7KnYcRhY)r4CW=D@q<>2o$O;lXv{xQc#X z^CHi)Ps2&5$os!D)i;Nim9@^d&c*6gk-K3yxVOBIUF@aG{%NW+zaJx|<@wikc*Je(ULJo0XPn2p;Fdu^ zI@n_i>8PLW441XY5c@l%iQNH^ratZaF&^WZlPAhS=H>9|(I{Nt7rZh~|6+6*(|A^u zd5rMkPK_N|sGhd}{nNB(wjoz=?qaF}tzowv+H)|banV=Qj)bw3X4g@lf&QPSomjAl zJ)%UfyW9RAKs|~WQ_4H0AMw)|+rFT5-a#mmcz6=qzDhTucd?Nx!I!9&%OR&9qsGR} zh)BbohS{Nm@c&!16T!~(8`$7hfHTzPLug`{jVx-^3gy%UU|u}5Yrl@2`gEO%$@ALN z0yBC_4rqko!7{{pC&}ppb>zX`D0J=YO91=AmhHV>lN~=z-sKC~pp%1MugNT)%>&Pf zM_V%;3l{nR!(Nl4_{so?R1>xb@|PWC5mP}rGWyRhXZ&yTqiio!$V|vN>?I;+b?68V zW{%zKyE>G<7+e96aO2cNfo?~_iT`kK?S*gwBKR&p&To&R)(sdDp5$|8QcqB^{miB#ztsuCRf-n-$zq53gu3SPnn>p^6Z%*fB z`_n}cRpWim%Z70P?@bW_wNNkt|F|h)W2F;{yX3HY&$%grpK;yka~g@x%W{l347B8q#?@q@I}E(hzl0J&?L%@tVcVcfvUu_Cr>0sZe*;syl52>h7rA{-GS;nS zBT$s zuU{~mNG{As7D&omR_U@6NXiyT*;EUYgns>}gjhWdGRZZ zUzzl+TiqZuVJgpLwUys?0Sl(5XIITjK+lZBL-?WvIfhs|}-EC>NMZyhZ? zuf4OqFa~2pz&d_^&KNJHP$%zP50LGQG20mcE-rIDP}uk4A7)w1!?clAU{WeQO}Qs_9KSH2Nl8)kKFz0}9xOMsp`{2;3vkAJ=1% zZJPhXXJe%BoUt7h_o?C4X@h+p8>mv3q@n$AhBV)ZA7yukYTwC-3+p&=VA9YIEQa}J zjKMTfNUM&6d$@ubIAqmc6KP8$A&6^Kvs6 zxjDq_c_(B>lsfrj4O}L*)+P!}NQ?>n(@%<;hL;H(DEfdgZJz-orXyUX`MpSKVlByp z$A!=3{_C^J8RZ_4soV?TOv9x#xkoy3w|z2ZlzX8}aRGL!_{6G$PU)n=bjQ8V#hZ- z5f+uuJ}uaf9a|e0$o?(FKMo_tL|_X!j!XR`89tGwdCNKe!8GLtY zgSrl6KC7FD;1nYs0J6PpGRK{`Ss-96b6FiR@kU1}Uz6SorTmSHF2wk&cTUN@spWDR z_eHuQo1HG3P>>!-AKG$Y$9~iBzscbOOnUIizpm?HZB*X zxbux_Y~h$=&hV#Y71O;Tz9C%@nTrj_!h~AWBTaGbtD&Zz^M?kqaV6m=8e@eCUsdUD zilb)y?oo@EnUzMVvX-#8lB|C)_|^T!k3KkL z!Xc@~v05_6ap(M9PdXetclFz|>VAd;gQL%bqoWowkJvfG$G`li7KtWj(5Jb;oZKBw4+&?yg7czhJtg%Xwy`80{*&#BsP=D!8lTi@K(I{;h-XH8i6-T!4fsrm^PN zPe?Km!pnp0+|>=>R-5}u3JvIvf#xnY%^e=LmffeWHl!1cB9n6wVaTXblK6hSrzRb% z^JwqCvW?w8AsH(W0^TBGgLb9tE&HQ8ut*G%DMXQ!+~Z9yX_SbMO9_#aoNn^K?H4RL zJCMhcN4Sm$M>8+OqysT`&dBZw>qir9B^hm{o=aOPAKFI#lQxz-OWIiS473p<$nAs= zZPMQzWOx0Br--(4jJEQewgvDe&E>YzW?XXQR$g3_x!hQC54>~miYib|MsqEpb&)tz47)SRquwg~TZ&e?JF0HZo-fLVC-Evt zrIye=a-1pl={++=-D6hqXpfhD8>g>Y&_*)ii?QloOHhl%$%I2vzklgPnd4Yg^Hz$H z;)6pL`}Uq0r*0}yT-Kfuj)A=*O^zeN^_91p*9iZs+B>HEw@-DVGL}&pC;ZeCPT_`B zdezi_tPk4OwP4jePFVSE6*L-w4)o!h zdcR$ysqKtJHJ`MzipS_&hgI`9p>x-R5tqo2+l?=O{HWXI?F*tz0wlhZ_JX^Yn5}#TGd)@B)#LHcRWUso;JiM zXJ%Vs@#_O|xOjS#a1?cL z3>>@+Ui*G|X8Pbb910u-eCSZbQN7>??`P{Bk5+}~kc^zNQKH@x&Wo2vwL^*SDO!~` z!DEE$3<{C1r$+OLMzK%0S@#2vJ3;t>%CIk!PCvoeT{vDWXvQ+v!ye5Tu#S$#E&2V(ZS+}ULP!((fh5J-qGRjl^K`f z?zN`{Rs30;)Y*Z;D_1N_Ed6MzrMFu4lVsG|+=H|h5%ZJK(I0HyNl^#1tZQoeg&vBY z9GVzsP>6&4xc6H{EOO6ds+3k^X(L?UVWTkJC65wDxy}y^Z&eQ}EATqCfM>iA&f}<7 zy&NQ^S64(3$5|;YPn*ipW}>w|STfUHUkcJG?*)+mWeFmGeju-Mpx;CEQIn(FR8e@80jDak9=K1?|AA*H}K0W)xS!sCtS#1>e#rn8CIiG7iXZgcG zA$4=GEbiIY*sfqNEi6F;BShq0`?Vytt58o?H#P1mX-ThCv?HE{MVaEq>%vXF+Yfn7 zW5wM0cEs3|0&Zg~7Hg_OpJ61pBzbpdg-WOjvuHv(h5t9%f?4npU~1bD4lr2W`VcbQ|I4^4X6kf6LGm! zgzJZ3NFPHwHsUKl*q*)3BApV3A;ksxm zP!REMo|aAb*TY|+mf8~-UgtqG#a&veMy;O7MPUUB9~Qh|inEjZ+j?=Y(jY2AL*trW-5-sM(+7Qso9P0^*PvkpK-ASwP4SobpCq++guYs=uCMP{^B+EG}Dc%%i5hQ^wSC#>%q( zesX>(eMYjlG_+2fnvy)mqy0@81^kVHLhpeNEe}%<$>KLP^GoW?Pa`C)WoS)FpEU*K z?idhhXLM`I_7rj0l42h9^qSXGv<>l*vc9rsUD^28qXITa?+-pT#SRxSc6z)J8C9(Y zkQ<@7WTSk8Yqng5wXp@pwearzb7VCozjiFA$y*M^oF>rr2t z3^D$da5%jfITl%zdo_?$k6$qYq|Db4M|WbS2enL)r+Cl=&Fd{_Cful6s&vv~gx> zj3(cB4KkXA5C?g+;v7rdeFXxbwAw(V)z`cdfnjai3wA~?-rORI&mK&X)rDQ5us3pE zko5tTp|JnT>wt7#f}wBR${$R%eNki-Uj-m|&*)6Zaz#9U0e9=NjEG2m%zR`- zS$fG;#16_wrbA00{4N)UApXb$pr4vdn0rWO|$?y0!H9W#Rp;3^e>%k^`h zaO$1cQpDA7Uo$}@USDjP7{^}uHJ685jir1M@kVcWj)d`RTXQp;B7z}c5kQdkY7&C9 zWF|{yFT+wYhHrcGM4m7DLri+Hj3QiDg3-WV4NSZfh_*d<0y;RmvwIFdcQ`-4r{@Q+ z{`oH3nQb=@34m z)xA3I6w0 zGJDQ~l5yhFAyB*sV0haIV0b$Su$UjPo@LIv2bR`L*UBKV{(<@yw*&9Ibe?!#86>>^ zq&}P-h7PLBOYZNY=c$i?Jx?J9BEEOIzJgdZA8IqiG7YAX7lGnMAZZQ)j}HRMmy^Vj zMYyj0LxvW~um)tfj>~X;5Sg&s|G^6<-IfSIo+nZtESbrbW646UUXnK1BxR5xBAzEh zCv6sjM7YHB|f1dAwCzG7A+Gp{zIBnD00LhV~f@wU6_=vhzjs+Jr9-8k_cTNhC zwZVjC%g<9h>9I)S%aJ)v^+d4>CdWef48n)n^Q&zSvpWB@#|+CoZERs0&+X;3?h6v8 z&-xgn_a#_;daW2}y*NKn)?b(gT4#4iB%K4up9dsU?A+sHS*_I{wEnsoAe}_eI&HWE z0xTwBG1ZUX0j&(nfZS6(>9NR!#Z*s~0<8?oq3xh`Dq)Fm-SCy`ja{oO_tl)ssivoL zS`P#XkAv$fVwt?hWi>fJX!U&ctE{^xgH{TGR)DOli;czgzN@3C6_$e5fj0s27Gz^k zh=Tx&B^J$l9PYr8mSZ7&>9NR!#ZrfmTp1R^$FW4XZu-i#Oo5LS_wBddBpo=)Y5kn( z04qI-O3(C`p5&AsK%fJx^kgbMnU`L##m`cB>4myD7FjHC7&-t=lDwK^rpMypIzVZ? znj~{gig4ZXrPbAQhT`bJSDe<9LBbll^e{%uJymkb3=xM8NUY3cDl-ftspJoC2ZeUY z^R!HVOwu38t3Rd>mV>tbm}<@bppapK{>bUEF#VB9e@uo2DskIaC9YEAZ>z*PPWpMK z5*Akp6sGAdOvx!sfIuZ!VJa#VLG~7AilY)7i^5d`iXeFv%S?}jDV9ZwmBO(=Ib=sA zezV1lWpKSKJ2!<6DGR*uPbSxO)&+|I_6^|*aWu&a%9B{Q~mzyLhuHG2%WlU;|njy zzv5PqfGJ>FP1clF}X*-LLA8&F&-3sEau}-(oz8mZi(^R@9V~vPoqe$QpZSV#{T>`$>=2t~yb;6)j3C%U1k-@=E*~)d$?3jl z(~V{JoxH2JXU7roym>mFmIjO-XCPxQ0C;EceX#haHq_-y0UvhQbLD^7a>syic91<_ zCxu8Rw(+U<8CZcT+2lxF@W@FST0rU z@JG{lb#uEwQ#;nLt)llh{?>k@-}|vPmItv7;>AN+o>X!ldGCZ8rg9U^b7Gvd`Z<_NNuQu9+; zZx|l$F+Lc&+Q#DLgEEq|)0M$TgzHaV0n7_-k?KzDGKtD_4i~_?!NR5KM-}mA?c$1l z>2`=|9O}}MFd`x~;j$&h&nRc9pL8jYs`uSFMX%j_kYrq_yVVBiAs$!6f3-iSs86rf zGPP>~I~9HO$>kp7LFLbgbYQ7J!A7sPe`SiKojP)WI{tgUbX}h`+j1Xk^a%}87IC^3 z2Mg-ieTw+y%1w%%u=}*fXmcw+Wr~QtT~e`rHx>JR;w#^kw3~lTlJ)+-ukaW@zV$g} z3XlO+UGZYxUf)`(`sOA{EBv6AqIdHAgnbMMaS%zZDvJeEi>9h4`@aZ>C%-RJ^mk*T zWMhsv%LW;8_JSo|YjM$1EB?~TqphD6r|9|4L}H!;A&#YBk0qA4C}FLvZZ@ID_ezgc z^mZ#|Nd|>%a-(-j;-}@6c(wjGOv`N9UR%-QUTl|QT;5sR2Jy10E`4L4q>Z}Tp33gN zuZ-&7Y7_4sUb1s4WVDLQXmzl#vj}R@vGzfh{$ri>d?O$_p&NMn$F) zNUC~gdFeQb$z$@ppeb&@ndt`!0Wi<$*lYTciAd$emmS0>UQ_>x{Quo9K* z22S-y!NQY$QzdbBgDLU)kno-!qi)y=A_)=2W`xFzse8lX)ol}#CGGeSG%W#(9(tUn z1t9Zxtd1AoyjM+Dsh(?8&-KI`7vhX=2Nw}Z09kW#U%a?}WnD$3)~^JkoB%dYnaB3 zy!UN#>o2GjFN)(!rK%)ajYO+=fVho15I3h~|D#|8QpK6AJ|bfdtrayQytQJ@2_u(*d{z3OqBcMSq)`K;Q=?>1qr^Fa zbW_F92?6oy^%v@ambIs4eOM)I*&FjiK|7;4DQi;2)mJ;kt6k#qnA#^V6j1czz01R- zy?D+BSz7U$B`(grBwnRvbE zw6$sZ_2?8yT%Rx{UTt{HEo;-h0eY`STd0QzlP&R`(`cXTqh@PVv-NUsW4hC>;{bX0 zvl6M|4YiV@Qv0CYr;_1{1I&B|7f^YPc#VZ>g%IZM0n;Ny7 zI<=(+wWS=(E8}8ivE8F@6}3KEU#&G-UwvTreUkC`3TvDmV(9zxuxGe5KNo)a@e}bY ziC;PVD&toZzgYYl;P)ziZSiZ5Uq}4<;x`1pvE+t(GCgL|1Abp3T`TCZo*p{_D+J)5 zN#PUpI7bgmK1N~^5|1bJm=uJ^9C{?vV;wzq&|@z>Qt5G&9$(Sp96c`4151;UIDCo6 zQ+iAa#$ygW7SUrBJvId6SOz=oPf-_!#D7&lxejz z96P)TI1UHotoOSZGmGf5$-dcoH@Q?|WFNTKgIpy+6e_4kG5k*xyvIvq=ES3<9S01% zqk1Z!y*aqIgToPQv-=D3y6^$vVxJwi3ztV=g@A+GK>{BT`-c~teHLRL`^X1A;k?B< zJ9PmSD-_P5fL0#x!reNs6$mkAv^SP^n|Nc{t`kQcqL>?aIC4kWjUz$_j2-O6f|%KiN|-=NV`2(Wcol`2OGSrHwxG_F z+CfTsv3^Bw(k00iyh+clh68#rW;V%$`@NuPWG`E6I$4Z)8y{?qI&g2jLvq6s6JPYv zsO>~PJQKqqEoL;I0qgCwFKjhIjLG56=J%qRqAefv>P z3N9ihm!&?~hw#@Fc0c^NF2a+kHuhTeEDm9&;>3Krw0kNl8*RSVg7yy+7um4~vfHjFUGv%OxqZ-Z&B$AGY9aa-tok_UzlW4=%eZ zS*`YtbZ5g@tCEvF$)_~jhsT2Zq6pdt#*(>4z^Q0d!UhW4AR7_(ie>btMgmI~)F8Ow zf6FJ97!w3+w$CPkyKI8opCes%A|jnjrVs;M=D0lKrjqmK$u-;;6Lyj0q|f{a1RXnQ z)v>WpTr} zlW}@YI7l*{HAtjQ8ZM#SjkB_7eSSGk)yiMlt2KSC5C7ip`dO2G*Ju6$KZM1t;k2CY z5)u#nWU8Z%9FerT_@p;TJc^xNrXA@dN>Tq@(OA~rS~-d*I(wXFlA^y+uGC&b{my|u z@{_E#?T9f~2|{+_))C1Vd?=15@=~ns{~6AP`Zj-=*6jyGCnqPpUg4q0-Fr7aWrt=F9{c-7-&Yu<2X^GM^onP?JG~hF5+K1wFOb_Ht zQ~6dWRtuth&2Mv%eNhywx?IJCojcC(as=bWgo`E4`zgI*!rg-?y=ps9dMXLLlZMhO z!Am18QHq-QYa?0vdCEvCh+;ywg&cK?-uM-io~;VSglb2BlEpr`hVNBJyon;D?|j(Y zmlt6%;qm$JxYDV0kD&;UbbUEafAk~NZ^BQnlbZREt^QTZy-!o_^d@JCgPcMxnpln% za&^0qOH53%9M0*8g3DDt9p~jU;k>B*G@u|Tl%n?93ylYVCHUn&G=`&1S$uvvaTxz3@)Hwyo%e2Y!X{v)Mc;jUMMat^GoI7@i2%P`)wMdjmoE zrAqnsLWzseB#z2h)P!$~&X&ao*s9K1+#S_`Sk#1EMQ5ArJ7>}Rz0K~u*e5%5F&z_t zlJzWZ!?W+gu*DK@dBkG>z(aQwfJHAJCtrKD+4~)MWRdU?eo6D< z`}Xb6ptMdY7T(o*kGtjU6Ew-%0W7*)Zwh&HPm{&3lcFu>&CK|wIB^V;=8%R*w_k}t zqZhUN!!kFi_IG1~>nNO@)x4Up+Z+@%;waj7fsQ3MjB}07Y1>pS-{FX>~xPa1sr+m49y!m?R6cNuEsoCRT`;31e#=-v>spXoz=NEobKYO^w2AJvE zyX@gw_Hd04RI`U`*~7K$;TjF&vWIKg!?pkShHIIQ%Q6|q{r84z8Lt|_QbzYA%vQc# zKWD($^_Z<3`z6g*I<9|RuOA zqW1e5$(YrvDh=2f4ux>oMi|4vcEI}LPzZ;j7SgbU&T#ChbPMMr2uFkqN2Bd~Is(Jb zuCA%LC-&||ROVu)LYPouVz?sSFW-=c<}epWMi!x*!-O^c4NFX%-APhke_^UeJM$Qe zgFS{yl5z6aIb6APM;7&MmwFv7gg6O`MTt_jClg0^M?Ace*1XfB3{3eHHhCdu1)$ zvl0<`zx+nIAUyz12Z!s;fH?%H$j!GD_x$RhGE z2vCf(tNbR2kQ@z$+cUTMzU;6<%HMD83MstJD+g&#{1MID=5CzSw`+fz(bcQFN=0Cm zOA2p)JUaD4n-!!PQc}v#X)J^a!67 z5bbfd&RtmodyY5qa&PBN7294|q^N)P!F%mzTAV6hM4EBmgI5jwikj- z_B#-b3S);t^LAf=<73zc*^Y1&DS&N|-#8H7+|~TW!ABQBKm(l9z(FCw&;VCyr^NVN zL5=XOS3fu1m!{Vs1$1r%X;yK)DY{qIlJ#DtK*OoRZAt32gtt%E!jbI1*U4)B+~8wH z@3yl3EFOF$y<$UbcyYZf9$STjn+vXCqmkGQ5Dmvd7W)g?5Tj4m!h!6+*O_Yh0+1!c zF|r)^=;z?@=B{pC23Z6*Mar}j#?Dkkjqr-cB*}fJ+Xxesdne|KCs^XQXHQ{51>1Iw zFRuMbluN=lk*8%*`#D}wgG++)N8vaMwQn>irx1e}Sv*0Zl%|@4cA~~3r5=i%t;W({ z(r}oB!%`_F$3fWA;o!Ne2JMMWpxh%|I9!Zcf>SObtnqgRxIcdKmxMzv4a3_APZH47 zl&4FaLR$9k+RxP}eB}HZ2i&n?HE8Q<xI#VPzZ;pX|GrYeqc8@ zy@`{tXS;k8Sw9rx@+m`BwrzHAv($fm93*M1Y$IIG!EVxs&5a%_=rLTR5pS{{qa*s( z8H#v$#JiSW)*WdY8{*<9zmDh>N-N@$#lwLb)833<@zEH(Rf@pwmqiwb@IkI_6@W zb1m^1sxXBZ#EIi^G|Jhms266GHMKRhX5cQa*TN*@jo)pEu(R_d;>8}rwAsDFo>#?6 zJjb!Q5#-UW+kQoDn_6AgI=mVy>-CRqNijZ(jO7p`Bd053Y}hh%P8*BJ+No17%6jip zuXv1(JznGxL;^-5x}uJl{7BLkFDt>npIzOMaOc4uzc}#T>*Fx~y<4{c1zM^q>QFPx zqfP!ZOxE{zfcz-LI2#$c0$cG?lN3HSX?(e&T?Q1gA@-PJKtLNsoqIC3q)j|3;BZCJ zvZg^HTRNz>v0-$O)0``5L!(N{`p6;AP@hJcR2N7`YFlE3L_<~|4#ED${%?H6zuzza zslvYN!}a$(My~HA{(WTReg&oaj-;;aaYoY2#D7V8!CiYj289?#l&T`G>3@RFf=gQ1 z+0Ja<+hcg;eY5peMcf_rqNSdFdkOZ#CgE)MFLfVyjDs~~PWPJrw&tpD4rnWB1rMVf z9K9YcL~gD@Tx~aXxzQGn@n!Cbl=E<5WMp|uJa8}6QlA7q#xdhggC)Jojs+g0@Zyq$ zces!^`>=_6ooK16e=dzPJRjwg^-F6aJqCps1k?Pmv%~Gyqw(b;wzg1+LF|q?FLN9} zuXw@K_Vvnx&a7_{$=G@&H-|WIuOji6+fuLPdEn8it-!?u7v?UNjP6MjIHeU5Ymh!| zH&wmCNsqSei|GBoSS(`I-5I@)*1l8`u*_)|ikLPDMCj_EVHxyLA-!1*Y1zf@t zVojy25iv4ymLx6_L+$;DR9~Hubw3*1~-&B;1c4bT3 zAc?cPk%Z4!>Xpu2vA-A>B!fPnXAu=H1g7%W&5e#hd(yuma~fv>I40(Gi)f*Nmh*af zM0G`Pc(avcSnEUV+?FKgqTKo_>g%;DnOe2Ixn=$Cm>=Sdj{9182^uGX=1F!Xu8`Ql zE|xX@7uX<|N4!Qg?KMT+5LXuW4=Gd8BGu3BF(||-n4Jp6n|NcUtiJv`x|anL&{#aJ zha+4R;vnFN^xj3~e^k;4J@2E^GOCaWEMaHYTk7y-lO*kYD>OVQ5bLxM6yjLc^uKC)vG{2sfTcnrT5?9q#9PxOt$a#xS+6=G z*fh$tjIy!BhM^$Sgfcs|hAk8d@r)Rj#Mz@P6=`LS((2la)3LMHi-pnBt=l?FMI$A1 zj)=E^a6S!$C{A)beWKv9tll?uu9C+EgVJ_usNI2nq1>ZS6gHf!!I zS)X|-STbUp&GJ&Zx-Kze*E?*xvkQbmUS^me6qQ)u%n)1YnNf%tMV-|@hs>D)Egm0Q zzzpSqD(5ic!GO(SW@IF*a*#&V&f{_aQ3F)m>Z5a*M!){7;zI138=*X6Vj$Cvl|#_& zG>4eH<+UwPxIChcB1UfhO;+DuJKdvA8-ObJc~r1$z_A5!0+7VnKd^D3qMoUXP2*Q5 z6qNO=v}v3|9E26_+0{MlPB}xB1C}MpID?H5s-ix6CtT9nl`V{t`xuQhg*cWI$Lm;} zmWO?(OWM0F&@F=&(}$MJBXm}{sI#_iqMnd$GD;bOZryI1nbbCij5Yn6Sn9fOaLnMx ztsnygd3?xV%*4cWr;M7=^g&s>a4F;?5{3nWFu6z|9LYx{Ot6d=AvxIO?FVYUWX&ThW{=PGIRYOiJnkOJ{7Zv6y{$8s>p5WCn(hY;hpY-STNuI?81QhTqJ; zF5W#m^*Wh%sZ<$Vt^-uKFvZ*KzCyMJUK?NjjLe8{EHHuB*sv?6cy{$gOP_UW+kRug z7b(OYB2F9+Bc1ueQYQshF}1DId$PW^(^qi@g*eFN5x8?BarR_O9s4M^sg=@Eo68>> z4D+`vtIfa?6LV0(Fs!ku9w>9lqkU6v1G=wA`z3=y9Ls=MroS~%0dl{KX_#CX=|)Zq zkPQlPkP;J{)1YAsF4-zl(4%eX23q2dmd4&0gdC6pCOZAIzydxr#s}j!aW>dLaUAS> zg@XH1ZniE$O$c_{va4JI0$wpO4xX&&jeg#;->CVhE1?BkWVTvxB1=D2X zx6F6}xl5Awo4_*1QYXyYxnG-?vm1>~5V1R|8JQE)$r#1!{qhd`5iVR3!!9BVW-8SB zD9z+GCKdXYx98uHl9Z4ko*xzc;>ZNqSYu2e#t?DfUWA45?0H4qdthOlHudmeS?^q{ zrfE=!gPdKxh)kW274_ltDw4KiOdnYvc)OTs6zbW>2DxAUOAGb^MknGmOe8d$jJuH% z@1e?nU%S5z61n-B1vM=xt0n$|1al62N7k2Df&}}Ne8-FBB4vab+sk|I;8a_^BuvKS zf8S#q?w4ePl$f{!x6wq+v(!&ZM#$RbyS@Kcch??QRk8gK=m8};B2u2MDOxJ&CoRQC zK49++hLq-WKQ!%@sYmk(nwikU7uxj^_!fK?m{yAUCKLAFps5LUtrXu$rdJa+>#Er; z`+e8UJ{(j|{r>v>@%w|#%$YSaYu2n;Gqcvr8aUGVa*&}Psx`U-BtUTy`6^)=+zVi&Eamye{gu#(Sw- zbYq(gvAj@LmbH8VOYUjtqxSpiNIHeQjUG%ajLD9u!RbO2x|=SXOOzRJV+b-Xso

qzR^HsM$le)0kw3?Rfoif+uNQg%zq3!AQr>c_8Q#}}NHZRj)W2sTJr3bdq9 zWE)Dlvp`fs&tg$XatYFiEecUlR%R;o9QG%j{+K7KU0=b}5W67I)G5R(%F2YZ(yYuO zmh#M;sOb5CQP<1Eh_Ij-$KuraOA|LH0WYWX)j%J zyQk7D5+W<%{R8p*&3sVz=AC(>zOr$M^h?zmxFQv8yv)XsR=RO_6=*3L8PN%)+* zUdKi^q!hjvl4It`O0#jeyqEC;ditZ#Rk1pSywp9&xkMpqFuGvP3I9qyAr-yt!9rI~ z64o7I&Z*p_GcAw{smQc@gcK5(kSa^@E2IFzgjCTDzd{NiOh_fi_!UwBVM40thF>AY zN`a6f<)j}W1rR2rQX~8dDFy-|l^o+&NCAWishp&{gj8tkj(nZO6)4R>Af!MSe?kf% zOh`pX`xR0EVL~c8+OLoT2oq8z#ZCPQDS$8`l~{I{klM8!LW;x{N0$kyw99^l6iV@U zAf!AVze0+Ez#SrS$z4Lq=AuP`Tu8-)WXL}DyGvXFgo&%HOuym^AWU3^l=>A{0Ab>) zU!Gra1rR2#vN8|)6ITFX;wmS}uef3$5Lc0De#I552;wR$)33M!2oqPJi$8G%kn+9| zS0SZ-#T7tuyF*-+_w_5T0MaiH;wmE7uebt8aty>(X|`W+1(3W(5LdK>^&_qr2*g!l znO|`QkjONMtK9B>#1(lQ9H!gF# ze@W{wMEm6}q^abh9YrcFB{S`4dLed8>4mc@fOnE9qKnD%Ivle|%f8Z%7TthaFum|S zTJWJ{sEKKja@LMI91`3aW}cOKDpOUVUNU#VMVc*I&4Aig-q!q3T)@FY8;+?v9l_3R zff1$IQ{o@=T-Xv9S(Y+}a=-~$#BA~@QQes^Waz6Cu`$VMoEeX;M?TqucLs(Qwat~;JC9LrDR9J&%Lp|qM|vmm>N^;ePCARZQEjE>pX$(;Pev` z7QuroWpBf#rrP-$CbdBa>WVsrIJyqUlO&jG;8ylHXgyy&$M(#~TXbVJt>1cBT2bju zL%-ae83>TjFAuu$^1j%zzj4has)IMpz+Kn2*eQQ|Y=&JZ?nK67!Gl?VsknUVOws`I zdIzVwXfVN=k>C7uf!b&xwD;9Uw~}-UagY{+C(`13fu+>xIK|-V`-cicB%Kub93;JP zE`c;>lr*6CLn+J_5mMUU2FYtQoOYFG48?8LG1b}uy(O*HuE97iF_Wn&S+C~MPIDxD zE6#$`h30G7JcI-gM?x=rCTZh3%!gt#aDGMiY$ct;8A%y;8m^7rcryt)>qWO?bqaCR z63c!jO<+w~`EyB_sTR+CPSn1C8GdfdFZ8fMa*~`f>TNA^OG;@rN@3XJDy$9CV(?cI zh&@VH_6>?M)aQQQFKU;b!WDB0@rrW0TOxQDLZ1=4ETy`wxx&p$n+7Gtdzb=UR`j?A zqT1y0Wb&K9wn%kdRmg z8%|!Mjj}Q-1I)GZDd?=v^nhQ>++Q;6LK$k{18N{t6(z+vwyGkrY?QBFnfO3fj%{uw zv3j*|$H@ZShe1dw%sAi!OpF5_kT~`)o_@`!gnfBmFl$z36r-dFkHMW7AK(U3+910k zk7p*WDd3>?;1ESrXP7-DZRD-GrcNPF111HqmxW3oVKH2Eb;4#c-0AfQ$izq5=r(b# z=xFSN!kj1h0`C;9z!GVJzsf$UlXm$!^$ilDqv7{FCuymyTu8hatFG?7QPc{8ATKDy zK~f_=AXb_tE1|pQi)wJR@kmIHsX<~G(U_3Q zw28PYdh@Ymc4~AqfbWZ5vr{9}F4MUjL>b~NTHg0C9q@r^FCv#M$Wcdm-w4wBe*h(@ zBf(H>wLK?lJJRdH=K(_AyrXGQ;tU33$e0l1W%#8RPT>iaqCRw4l`QJRz~kx34$g=; zVw6k01Pq|PHZdd)$;z}qc%!&j1RLh32fE`efjdk@0VF4>A#uz#o9`&EM!4u?*5aj< z_w7lRyeqQuz>l(|E;#&8QQLF+Lcad<+;?mcpi6d#A7v%%JxNlhXl_s!ywKr7Caj$&Y4bKh?@l3JQDoZtq%`Xd?UD$q^~g&w z?(}*z2$tJJb8V3H!acOW%d^eawt^qLZ7cXuQC=gIQgoxIteou;WU4PUAO-*IG*PDz zuP8aD9WBjZxSmuu%2dVfz-8I>U{R+K2Z_inC3)->dQ36Sn9rX4P!UX_j4rYQYDg+k zL+iBp^MXorNh||(%TlnX=r<7F#29s(o_H2Mc`B%j7Li5k2}q9haNCpJ`Y9WO^1kRx zoLG>whUadHdde+tU(&hp3VF$5oIlvwV zF>F;i>69xJ?xt6}43OlQhpEf1OUkn2P?h&-4(rs@2O-pc8`IFPi1y@Mp514d@)iKS zzo}f^ABa;{Ct(a~EzdXfc8^Bd1u!&HBc8RC1_BIIZCqHnRCd#eku=whbI0F(J2T;k(CDN*eAdP>XY* z>6~S>k@P1=F-<2xqNB&t9w5_F;^i1aot68fq|Gq|Nv9C6C?{zJ8SkF4lKEs6koNj7sT8Wb0Ep?JzKzZMnXq>%cC?7;(v}T;|AZge4 zW3*C;=PgTFNrPyXq&yUb(HhmTfu!~M9p@}4#6e<0KBnaeRPUI746l(Cqt(}#etB7> zU|J$8U-qsE_mYuNQ?+&AA$SUTD;hwP)gFx2=+>s%^5PTVqH{-MbqaA1k7ub#eQr+` z<$VX-N42!eP3Y)=B`fRqw1bcDnb00(X1-sbQ;3(68WBW7a=ok!m+=h3l0CI0ZR0>Z zOSN+AC=&djUur~iI$*IJs>E;Li^do~nkI2?!p+Al+5jPnmeb%xlx1Vl#IidkO~eK! zV%@H?qv{I({B%`EOKOw%7w9m%22N zw75~SHt$PVu^;-}Ng0uVg#@*DjI0cs9AKzlgyXpuW87mnCiF5p@&%Bxl%~Xx)9rbT zow#83QhV_OkmQ&jO|a5fS-BqATvWprmcTo!Bhu6lDl5+wD=jv`Te==oSfZ@#zC2Fc14XtT5ke%klNNUE3yN#La78PBE{ zGLhqrmZfB{wILSb{QMdcJRX}6%F5~Q7%C$~xYOsO7NW%S!Nx+EA8L@}gWX(|d`6wx z78>lHL4|zI>X$c;D2Rmg!W|+=`@5wCHNRY-?i|of(&~Q&NKVo!T9lVq%F)&s z1&2$pcS-scqkuvj1j|+0Zcbx@(ok9PPAZ-yloXGm#T%j?PYUT2?uzCl{nO;B4EUZX zaHiuP$lGFYI%LA#Q6Dh&V8pfFqFB^d5zkBYvPQEgq04!-UmiP&fI1@6z9D|vWGQFg z!tgkD?vkke7~k5^Da7+)WkX9REEVptYO)m)EB@wVFVP|&AjhUAm}~ze-Gl%jX%1C+7y4}y(t!d zbOH4x{LLU=OWE`(q|XWZOr-+W(PtZdcG2e~eQwfcA^A|+O&`ZS{!2{mO(_xAQ1RR} zZk{%ZFCbqejpA?ee+$Ts3-ewgMDHZ8BKLs3hjc)HRtd}`S0?v>&E;V0DuGo2^(C+K zd;H^dGEXt_^m77TfIvko%?=Za{CDPGhr>A>KgD_B*nNpc@mF|x?I}OY!+sZ{p9Y@r ziNjhvfOUxw-5$S%0gi6!+D=SI0he^?*)U<5Mn0#dxGEZCK`I!wl|peeq0J&Yb^ z;TM~fEKFXu&_~Sg6E6r~l!5QP+3lS8$1(}gO_7oLF~Uzan={^`>k7D~O}Bf{3oOY? z7;*;Y4Ik%KgK*48nD=K^gv~292-?a^q0{Loxx@dyWWvi^a^=eJt3`-zf>JqE2Q(}t z=4N^AFoUO?9r&FM8avDe01MkhL}j@7QPFA^wnrcf+oLDA(&)kOe|tk+a`^lS1>%Of ztLOM3!(JITqA`CoKDe^0rVHd+$m^=9Rv)lQZ2JG?tLbkD$%rU9Vlhw2%K{uAq?5b4y15}Ou7<<$PFzig<7@7ksT}Eeh?=D* zOd2zWyJ&KqdQ2zz zK~GcHh#xX0dD8F~nWLXdzlYerw`tYZSsifp6V~+ZUvT#cxWtCvgK(}V7^OMrO>0(~ z4OJs_LdF;aKfbY(T&>t{yK9E3A0IPZDeZdE`MVI<9DlMnRJ~;wJ_v6a_Ny5T0ysN#Dh>1Xs=#J7 zTP`9;7!}yo{;vGDg3#>XLfJKC$Y#3WP)DJm^N$`LcliM{mXQr zqwrO;+xF|u(^l*v2w*!MAqIi$Y$rvC^6Yr*_1^4s<{CRT%EWhUR1gqd9oP(LSApnn zc`Yp0hNuiOVz?P?1-IcJQNg{K9#^aiQC3rslV$gZs4u&XC~GI9sEz0ve~2Dv*+_CF z4gQpvAd(^4*gX^U66yyE_S=fAFh*7zm&Wd;^o|B2JXNBu;gkbeZOXASjEXWu)msL< z@p8iZ%CMP$bsj^RN&{`z`a`)q__pMVN|`{kZO%}Ra(_rDqqFZr+3x2k_l`SDJ5)m1 z<`u@bj8|A0MnxGS?`*cEvr+byVWZ3#hM~-w9qxS3AIjJEZna!J@2uzwlv^>BTmLP} zt=&B+x8WL!G259 z9_;Pi7|I>~N*u79OdPPTsX`q1%BUbKgpN&CCUh#*?h{MkknH=#MCgcpU1e9nhT*i2 z?#ghF@!{?j6ZZ(U827e;S$`?iSQ%Bff{Cmkr>~5vTM_QesRG*r-#abW^uC*D^u;r5 zySeA4&d0UCPZMIb{GO)`eeq_d*ze|keba9RLTH)}%jUnE6sSw^yEf{2tfW&2qO6-c zAbT2~7fatKDwI=YIi2{ueZo#d7#Nm8>Wpq~XOiC#xNecarP}qXgFaU)z!!S^U%wppzMw`(2_pxs5Jv6 zVd5ukOs({6V>}kKfVHrX`$%asQ#g`x$xt>7O~#En{H|T!SqqPVcp+9CJZuPG3{I02 z%E=&D`PQ$iZA`*p;^u83te<@N3E4HM)>INE^rEyAFG{!HJWUeDr|&aZtp8*bgcWL(y~Sf!Kv<#vu*-y*$4!J4BGwEv@1mW@O@tLLl{TwHJ1uliW1RNm)b+TD zutMR%!=ge|_fps6rY;sXU0)r;>SmaX>j+H3og2JZ`=;{H4NtF@UFKIUiRMWR`($_N zh{GcF8{wPmo_lI}jIi^TgU8%xln^;%7>`k-ga#AFQGX=6sZoNyJCY{zWH&X6_y#BD zD&d{%rbY>+DVHkYtq})#TbAsmMzQ)8%E?<6?)}$QYPIf)ji%G{+U?1ds!~N`k zw;95kUR$s_n6fNZZ@PxbtvB5HX9i0`@Q^G+Sy+g3g_klQc}7||SNPhRbn>tGhWmDj z2Y#tPcbLjgBfk~ZZ4KsB{Ep)zZ9Xp0l5Wfp^=;?IQVZ>x=6te6RGJDn9s0I3mFCKi zs*o-9au%Ad`n~@o9+|<9CDh+Z})fYgc5ycVhKxqaPsOjwog5^dM2# z1x{Ap9|;huh$qy1wJlza`elHrEzECg>Q6MTOt`6Q_ui^Wd@`4}U|xXx z!Ea8BLfS#R0CP4Plw9`A6`~9ho}M@(U-&g?jH&dRjhhOCzF_7~Bz*K%9aG5fG)&UQ z{<$bdKe@=8z>3Os_7#;jgo*O)&(7G2deLQfq?E0TxERPFgF^ndtja8i&HAcu~-(Ls@qTS_umPu)SR z=cI(#UN2gNnaSa{#;%fB3$!z4yy0y<;AYoMkg4^eLT%=)Cpvgr50I5|Z<$d}i5j~J zPAIAMtny7C3bGLPYl5ZGc+fxL*1}QLf2@3$%(A&vP^9ViTTNG! z@<}uieZVQQKEVB@3^igGqpPKv)jOK{>qU={{+=gT!v48iOy%0au6WwBi<|WPNLZ(D zg6%$dlpSRSOgYrmLbaQ#s`iVmSV{jniMVwWuQnHtrkh7h;g5etSz2!}r9PN5B@(K| zuEg~4eu1eF8>`E~#@f-#U=f?40aCjYPT(Z;e9lyE8;fGp(Ki_1BH;^Jx2P@f(=Z?- z*4q}IAPb+*-6AP3o`xzuowo%EEA&mUO$RgmGooR~ftB%Q6t(4(D%$dF)0ZsQzje;>#Be&1fac1=s8{-v5}QXY;fc*>OzqR(Kg5Cd zcIYscu$ejxaI(_64^9Z5JixjbIo?c&l!dRqI&Nr-ollvSs(i{oi-grbZp6Gv;GCDoR%NzL^oLe)l=r67Jj@*lgAQD|ZWk z_gfy8U4h}%2(v@HuZjcQ`)6;Igp+kASjvCnF~Gi9_Aw1GB*cXoqA>5>p_cX-MxL(m zk%xpKYeymB*G4hQ6bTI3{dLH!bdp({xXc1buc?P|60lFatlY|uH`IWuY}6v5-X9Z9 zs!i6`c7!Onw#HlAC&kMo;g36+qVn&P;EbGacS+h;@!$*!p+VcKXi!05u}P%1(4cQQ zsgE#HL!v!{_nU*9h=SCzFid#f)Q(+%^s-6K6D(my*?39$PJ(gQCN&ZcZ+RAP`%FH9 zd+ZqJUQ$;sS$V{P!(}$9w^xB#i=%5SSCiR}$#GZ&6SO*I; z-)>`Ru8tpx`Z?Inc*2*n9+e3W=FqWV&uwoq?%+AV1bYHyjrdkS#rd{!$qI408cduX zjyDtUXM(jY4_mHdb*d4~e&9@SKEVCZ+EIq^)~}87wdN##?T$o(KJ_pT?e>Ycl+(@O z(8caZBvkujB4-=z7a22}-H}KrDPCp@OaII?6zV?Sk<_KUBZKfnh5KK#H*zLWcAvzI zX0sd;MuZuLF#lb=wnkH(m*tR9fuGX#J8%cF9NM?jZeN9(t48S29SdYv(51yzC6&GBqD!mj~tTCWP@jAnOl zf{;MVWZ}^A!-lfny99>Rp{y5=gC&HM21Pz*}~d7R|z= z(U)n~N9wCsH4DpU4U{x0)VnZ70z+fyPq-%Js|$UK$0f@ZN*5e4+Uxt&T4k;HmQ+na=}&q}Cf@3g-&i zNlLd5{$r?5|NI=Gi-gfPQzT(e1~hj48y_?DHv&yNp`tdWXbcuO6KCTnUbyqq`_^CH~!_l1^=zef_YnWTH+R&&<-L4V|buYHW^s@Y{q!5xSA*rpXG|K@b z;`^T@;rWfY2v1Grvt0ak> zXl&);i|4R}PJ8eo7vZPd({AOG6>5>nS`>~)YPk4{aE8E8O3&z!5jGNk&GFX?f9>$s z6@T&g>y1BpLT5PslJJ*`KW3PnOXk>x^vR;n2lUxQpI!7RqR%1vd`q8G^!b54*XVPL zKGVr!JBL0?0`IZb4r4xsuaf=CYfVccyBS$1aa5Xu&oJu|e)U>+$ii=floUfyaggZf TRO|0-ILzWu%|XToW`+14DrG!( diff --git a/packages/smooth_app/lib/smooth_category_picker_example.dart b/packages/smooth_app/lib/smooth_category_picker_example.dart deleted file mode 100644 index 86263096ff9..00000000000 --- a/packages/smooth_app/lib/smooth_category_picker_example.dart +++ /dev/null @@ -1,222 +0,0 @@ -// @dart = 2.12 - -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:openfoodfacts/openfoodfacts.dart'; -import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; -import 'package:smooth_app/generic_lib/dialogs/smooth_category_picker.dart'; -import 'package:smooth_app/widgets/smooth_scaffold.dart'; - -void main() { - timeDilation = 1.0; - runApp( - const MaterialApp( - debugShowCheckedModeBanner: false, - home: SafeArea( - child: ExampleApp(), - ), - ), - ); -} - -class Fruit implements Comparable { - const Fruit(this.name); - final String name; - - @override - int compareTo(Fruit other) => name.compareTo(other.name); - - @override - String toString() => name; -} - -class FruitCategory extends SmoothCategory { - FruitCategory(Fruit value, [Iterable? children]) - : children = children?.toSet() ?? {}, - super(value); - - Set children; - - @override - void addChild(FruitCategory newChild) => children.add(newChild); - - @override - Future getChild(Fruit childValue) async { - return await super.getChild(childValue) as FruitCategory?; - } - - @override - String getLabel(OpenFoodFactsLanguage language) => value.name; - - @override - Stream> getChildren() async* { - for (final SmoothCategory child in children) { - yield child; - } - } - - @override - Stream> getParents() async* {} -} - -FruitCategory categories = FruitCategory( - const Fruit('fruit'), - { - FruitCategory( - const Fruit('apple'), - { - FruitCategory( - const Fruit('red'), - [ - FruitCategory(const Fruit('Red Delicious')), - FruitCategory(const Fruit('Fuji')), - FruitCategory(const Fruit('Crispin')), - FruitCategory(const Fruit('Pink Lady')), - ], - ), - FruitCategory( - const Fruit('yellow'), - [ - FruitCategory(const Fruit('Yellow Delicious')), - FruitCategory(const Fruit('Ginger Gold')), - ], - ), - FruitCategory( - const Fruit('green'), - [ - FruitCategory(const Fruit('Granny Smith')), - ], - ), - }, - ), - FruitCategory( - const Fruit('berry'), - { - FruitCategory(const Fruit('blueberry')), - FruitCategory(const Fruit('raspberry')), - }, - ), - }, -); - -Future getCategory(Iterable path) async { - if (path.isEmpty) { - return null; - } - FruitCategory? result = categories.value == path.first ? categories : null; - final List followPath = path.skip(1).toList(); - while (result != null && followPath.isNotEmpty) { - result = await result.getChild(followPath.first); - followPath.removeAt(0); - } - return result; -} - -class ExampleApp extends StatefulWidget { - const ExampleApp(); - - @override - State createState() => _ExampleAppState(); -} - -class _ExampleAppState extends State { - Set currentCategories = { - const Fruit('raspberry'), - const Fruit('Fuji') - }; - List currentCategoryPath = [ - const Fruit('fruit'), - const Fruit('apple'), - ]; - - Widget _addCategoryDialog(BuildContext context, FruitCategory parent) { - final TextEditingController controller = TextEditingController(); - void addCategory(String name) { - Navigator.of(context) - .pop(name.isNotEmpty ? FruitCategory(Fruit(name)) : null); - } - - return SmoothAlertDialog( - body: TextField( - autofocus: true, - controller: controller, - decoration: const InputDecoration( - hintText: 'Enter new category name', - ), - onSubmitted: addCategory, - ), - positiveAction: SmoothActionButton( - text: 'OK', - onPressed: () => addCategory(controller.text), - ), - negativeAction: SmoothActionButton( - text: 'Cancel', - onPressed: () => Navigator.of(context).pop(), - ), - ); - } - - @override - Widget build(BuildContext context) { - return Theme( - data: Theme.of(context).copyWith( - canvasColor: Colors.lightGreenAccent, - scaffoldBackgroundColor: Colors.lightGreenAccent, - floatingActionButtonTheme: const FloatingActionButtonThemeData( - backgroundColor: Colors.green, - foregroundColor: Colors.black, - ), - checkboxTheme: CheckboxTheme.of(context).copyWith( - fillColor: WidgetStateColor.resolveWith((Set states) { - if (states.contains(WidgetState.selected)) { - return Colors.green; - } - return Colors.black38; - }), - ), - chipTheme: - ChipTheme.of(context).copyWith(backgroundColor: Colors.green), - ), - child: SmoothScaffold( - body: SmoothCategoryPicker( - categoryFinder: getCategory, - currentPath: currentCategoryPath, - currentCategories: currentCategories, - onCategoriesChanged: (Set value) { - setState(() { - currentCategories = value; - }); - }, - onPathChanged: (Iterable path) { - setState(() { - currentCategoryPath = path.toList(); - }); - }, - onAddCategory: (Iterable path) { - getCategory(path).then((FruitCategory? currentCategory) { - if (currentCategory != null) { - showDialog( - builder: (BuildContext context) => - _addCategoryDialog(context, currentCategory), - context: context) - .then((FruitCategory? category) { - if (category != null) { - setState(() { - // Remove the parent from the set of assigned categories, - // since it isn't a leaf anymore. - currentCategories.remove(currentCategory.value); - currentCategory.addChild(category); - // If they added a new category, they must mean that the - // category applies. - currentCategories.add(category.value); - }); - } - }); - } - }); - }, - ), - ), - ); - } -} From 087b21c2c8153772dd6d6b8c03c1ea9f9ce3eaeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Jul 2024 20:45:41 +0200 Subject: [PATCH 67/85] chore(deps): bump flutter_custom_tabs in /packages/smooth_app (#5481) Bumps [flutter_custom_tabs](https://github.com/droibit/flutter_custom_tabs) from 2.0.0+1 to 2.1.0. - [Commits](https://github.com/droibit/flutter_custom_tabs/compare/2.0.0...2.1.0) --- updated-dependencies: - dependency-name: flutter_custom_tabs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/pubspec.lock | 4 ++-- packages/smooth_app/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index ce041dcc8e2..6d18732932e 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -510,10 +510,10 @@ packages: dependency: "direct main" description: name: flutter_custom_tabs - sha256: "961fe962ae55e9e41097c34e68c6d7d2de10e9a71034f83834919e31a891e728" + sha256: "34167bd15fa3479855c011f868e0789c9569c12b64358ca7250accc5a24c3312" url: "https://pub.dev" source: hosted - version: "2.0.0+1" + version: "2.1.0" flutter_custom_tabs_android: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index 1643c916804..d98374bd3e1 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -64,7 +64,7 @@ dependencies: webview_flutter: 4.7.0 webview_flutter_android: 3.16.4 webview_flutter_wkwebview: 3.13.0 - flutter_custom_tabs: 2.0.0+1 + flutter_custom_tabs: 2.1.0 flutter_image_compress: 2.2.0 connectivity_plus: 5.0.2 dart_ping: 9.0.1 From 5136e9d81243ddb38902e5dcf911d831b4d40e40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:08:34 +0200 Subject: [PATCH 68/85] chore(deps): bump sentry_flutter from 7.18.0 to 8.3.0 in /packages/smooth_app (#5477) * chore(deps): bump sentry_flutter in /packages/smooth_app Bumps [sentry_flutter](https://github.com/getsentry/sentry-dart) from 7.18.0 to 8.3.0. - [Release notes](https://github.com/getsentry/sentry-dart/releases) - [Changelog](https://github.com/getsentry/sentry-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-dart/compare/7.18.0...8.3.0) --- updated-dependencies: - dependency-name: sentry_flutter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * minor fix --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: monsieurtanuki Co-authored-by: Cirrus CI --- .../smooth_app/lib/helpers/analytics_helper.dart | 12 +++++++----- packages/smooth_app/pubspec.lock | 8 ++++---- packages/smooth_app/pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/smooth_app/lib/helpers/analytics_helper.dart b/packages/smooth_app/lib/helpers/analytics_helper.dart index ab200150067..5170bc65a53 100644 --- a/packages/smooth_app/lib/helpers/analytics_helper.dart +++ b/packages/smooth_app/lib/helpers/analytics_helper.dart @@ -221,9 +221,9 @@ class AnalyticsHelper { ..dsn = 'https://22ec5d0489534b91ba455462d3736680@o241488.ingest.sentry.io/5376745' ..beforeSend = ( - SentryEvent event, { - Hint? hint, - }) async { + SentryEvent event, + Hint hint, + ) async { return event.copyWith( tags: { 'store': GlobalVars.storeLabel.name, @@ -265,8 +265,10 @@ class AnalyticsHelper { static bool get isEnabled => _analyticsReporting == _AnalyticsTrackingMode.enabled; - static FutureOr _beforeSend(SentryEvent event, - {dynamic hint}) async { + static FutureOr _beforeSend( + SentryEvent event, + dynamic hint, + ) async { if (!_crashReports) { return null; } diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 6d18732932e..0fd789bda82 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -1370,18 +1370,18 @@ packages: dependency: transitive description: name: sentry - sha256: a460aa48568d47140dd0557410b624d344ffb8c05555107ac65035c1097cf1ad + sha256: "7342ef4c18932881730ac941a07a6e4cf76fe99cd1ea3bef06e53a6a1402dec0" url: "https://pub.dev" source: hosted - version: "7.18.0" + version: "8.3.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "3d0d1d4e0e407d276ae8128d123263ccbc37e988bae906765efd6f37d544f4c6" + sha256: "475cf49682e4d1eb48caa2577502721bcfdcbb63f215de57b3b246d52f4f7914" url: "https://pub.dev" source: hosted - version: "7.18.0" + version: "8.3.0" share_plus: dependency: "direct main" description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index d98374bd3e1..d0483b91117 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -37,7 +37,7 @@ dependencies: photo_view: 0.15.0 uuid: 3.0.7 provider: 6.1.2 - sentry_flutter: 7.18.0 + sentry_flutter: 8.3.0 sqflite: 2.3.3+1 sqflite_common_ffi: 2.3.3 url_launcher: 6.1.3 From 8264ee08497a6f4238057b374bce4db6969ed15a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 20:42:57 +0200 Subject: [PATCH 69/85] chore(deps): bump flutter_secure_storage in /packages/smooth_app (#5485) Bumps [flutter_secure_storage](https://github.com/mogol/flutter_secure_storage) from 9.2.1 to 9.2.2. - [Release notes](https://github.com/mogol/flutter_secure_storage/releases) - [Commits](https://github.com/mogol/flutter_secure_storage/compare/v9.2.1...v9.2.2) --- updated-dependencies: - dependency-name: flutter_secure_storage dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/pubspec.lock | 4 ++-- packages/smooth_app/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 0fd789bda82..4eb4e3e3ea6 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -664,10 +664,10 @@ packages: dependency: "direct main" description: name: flutter_secure_storage - sha256: "8496a89eea74e23f92581885f876455d9d460e71201405dffe5f55dfe1155864" + sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" url: "https://pub.dev" source: hosted - version: "9.2.1" + version: "9.2.2" flutter_secure_storage_linux: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index d0483b91117..f0619116fbd 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: html: 0.15.4 flutter_widget_from_html_core: 0.8.5+3 fwfh_selectable_text: 0.8.3+1 - flutter_secure_storage: 9.2.1 + flutter_secure_storage: 9.2.2 hive: 2.2.3 hive_flutter: 1.1.0 http: 1.2.0 From 1118349b00c1792f399c21805d2f7743dc09d9fe Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 20 Jul 2024 09:46:53 +0200 Subject: [PATCH 70/85] Remove all unnecessary `MediaQuery.of()` (#5459) --- .../bottom_sheets/smooth_draggable_bottom_sheet.dart | 2 +- packages/smooth_app/lib/helpers/keyboard_helper.dart | 2 +- .../lib/pages/image/uploaded_image_gallery.dart | 4 ++-- .../lib/pages/onboarding/reinvention_page.dart | 12 ++++++------ .../lib/pages/product/portion_calculator.dart | 3 +-- packages/smooth_app/lib/widgets/smooth_scaffold.dart | 10 +++++----- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/smooth_app/lib/generic_lib/bottom_sheets/smooth_draggable_bottom_sheet.dart b/packages/smooth_app/lib/generic_lib/bottom_sheets/smooth_draggable_bottom_sheet.dart index 29644cff0cc..4b33885c2f8 100644 --- a/packages/smooth_app/lib/generic_lib/bottom_sheets/smooth_draggable_bottom_sheet.dart +++ b/packages/smooth_app/lib/generic_lib/bottom_sheets/smooth_draggable_bottom_sheet.dart @@ -84,7 +84,7 @@ class SmoothDraggableBottomSheetState : widget.initHeightFraction, scrollController: controller, cacheExtent: _calculateCacheExtent( - MediaQuery.of(context).viewInsets.bottom, + MediaQuery.viewInsetsOf(context).bottom, ), ), ), diff --git a/packages/smooth_app/lib/helpers/keyboard_helper.dart b/packages/smooth_app/lib/helpers/keyboard_helper.dart index a478f05e226..0f12edef4ea 100644 --- a/packages/smooth_app/lib/helpers/keyboard_helper.dart +++ b/packages/smooth_app/lib/helpers/keyboard_helper.dart @@ -1,5 +1,5 @@ import 'package:flutter/widgets.dart'; extension KeyboardContextExtention on BuildContext { - bool get keyboardVisible => MediaQuery.of(this).viewInsets.bottom > 0.0; + bool get keyboardVisible => MediaQuery.viewInsetsOf(this).bottom > 0.0; } diff --git a/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart b/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart index 4bfdb032e7b..8b20e3103a0 100644 --- a/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart +++ b/packages/smooth_app/lib/pages/image/uploaded_image_gallery.dart @@ -38,8 +38,8 @@ class UploadedImageGallery extends StatelessWidget { @override Widget build(BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); - final MediaQueryData mediaQueryData = MediaQuery.of(context); - final double columnWidth = mediaQueryData.size.width / 2; + final double columnWidth = MediaQuery.sizeOf(context).width / 2; + return SmoothScaffold( backgroundColor: Colors.black, appBar: SmoothAppBar( diff --git a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart index 690c8833d61..31cbedb7440 100644 --- a/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/reinvention_page.dart @@ -20,7 +20,7 @@ class OnboardingHomePage extends StatelessWidget { return Scaffold( backgroundColor: const Color(0xFFE3F3FE), body: Provider.value( - value: OnboardingConfig._(MediaQuery.of(context)), + value: OnboardingConfig._(MediaQuery.sizeOf(context)), child: Stack( children: [ const _OnboardingWelcomePageContent(), @@ -186,7 +186,7 @@ class OnboardingText extends StatelessWidget { fontMultiplier = OnboardingConfig.of(context).fontMultiplier; } catch (_) { fontMultiplier = - OnboardingConfig.computeFontMultiplier(MediaQuery.of(context)); + OnboardingConfig.computeFontMultiplier(MediaQuery.sizeOf(context)); } final Color backgroundColor = @@ -265,12 +265,12 @@ class OnboardingText extends StatelessWidget { // TODO(g123k): Move elsewhere when the onboarding will be redesigned class OnboardingConfig { - OnboardingConfig._(MediaQueryData mediaQuery) - : fontMultiplier = computeFontMultiplier(mediaQuery); + OnboardingConfig._(Size screenSize) + : fontMultiplier = computeFontMultiplier(screenSize); final double fontMultiplier; - static double computeFontMultiplier(MediaQueryData mediaQuery) => - ((mediaQuery.size.width * 45) / 428) / 45; + static double computeFontMultiplier(Size screenSize) => + ((screenSize.width * 45) / 428) / 45; static OnboardingConfig of(BuildContext context) => context.watch(); diff --git a/packages/smooth_app/lib/pages/product/portion_calculator.dart b/packages/smooth_app/lib/pages/product/portion_calculator.dart index 34eb43dc486..02dce603b75 100644 --- a/packages/smooth_app/lib/pages/product/portion_calculator.dart +++ b/packages/smooth_app/lib/pages/product/portion_calculator.dart @@ -37,7 +37,6 @@ class _PortionCalculatorState extends State { @override Widget build(BuildContext context) { - final MediaQueryData data = MediaQuery.of(context); final AppLocalizations appLocalizations = AppLocalizations.of(context); final bool isQuantityValid = _isInputValid(); @@ -66,7 +65,7 @@ class _PortionCalculatorState extends State { textBaseline: TextBaseline.alphabetic, children: [ SizedBox( - width: data.size.width * 0.3, + width: MediaQuery.sizeOf(context).width * 0.3, child: Semantics( value: '${_quantityController.text} ${UnitHelper.unitToString(Unit.G)}', diff --git a/packages/smooth_app/lib/widgets/smooth_scaffold.dart b/packages/smooth_app/lib/widgets/smooth_scaffold.dart index 66e355fa3d0..9dff0baf264 100644 --- a/packages/smooth_app/lib/widgets/smooth_scaffold.dart +++ b/packages/smooth_app/lib/widgets/smooth_scaffold.dart @@ -66,7 +66,7 @@ class SmoothScaffoldState extends ScaffoldState { Widget build(BuildContext context) { Widget child = super.build(context); - final MediaQueryData mediaQuery = MediaQuery.of(context); + final EdgeInsets viewPadding = MediaQuery.viewPaddingOf(context); if (_contentBehindStatusBar) { final Color statusBarColor = @@ -79,7 +79,7 @@ class SmoothScaffoldState extends ScaffoldState { children: [ SizedBox( width: double.infinity, - height: mediaQuery.viewPadding.top, + height: viewPadding.top, child: ColoredBox( color: statusBarColor, ), @@ -98,7 +98,7 @@ class SmoothScaffoldState extends ScaffoldState { child, SizedBox( width: double.infinity, - height: mediaQuery.viewPadding.top, + height: viewPadding.top, child: ColoredBox( color: statusBarColor, ), @@ -109,8 +109,8 @@ class SmoothScaffoldState extends ScaffoldState { } if ((widget as SmoothScaffold).fixKeyboard) { - final double padding = MediaQuery.of(context).viewInsets.bottom - - MediaQuery.of(context).viewPadding.bottom; + final double padding = MediaQuery.viewInsetsOf(context).bottom - + MediaQuery.viewPaddingOf(context).bottom; if (padding > 0.0) { child = Padding( From 1573d329491cb49ddf9c6f275ee2a32284855b4b Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 20 Jul 2024 23:17:45 +0200 Subject: [PATCH 71/85] feat: Country selector redesign (#5483) * Redesign of the country selector * CW * Search filter * Fix Lint warning * Small improvements --- .../lib/generic_lib/design_constants.dart | 7 + .../lib/helpers/provider_helper.dart | 117 ++++ packages/smooth_app/lib/l10n/app_en.arb | 4 + .../pages/guides/helpers/guides_content.dart | 8 +- .../pages/guides/helpers/guides_footer.dart | 2 +- .../pages/guides/helpers/guides_header.dart | 14 +- .../smooth_app/lib/pages/image_crop_page.dart | 4 +- .../pages/onboarding/country_selector.dart | 359 ----------- .../lib/pages/onboarding/welcome_page.dart | 38 +- .../country_selector/country_selector.dart | 592 ++++++++++++++++++ .../country_selector_provider.dart | 292 +++++++++ .../user_preferences_country_selector.dart | 3 +- .../lib/pages/prices/emoji_helper.dart | 13 +- .../lib/pages/prices/price_data_widget.dart | 2 +- .../pages/product/add_new_product_page.dart | 15 +- .../edit_ocr/edit_ocr_main_action.dart | 2 +- .../carousel/main_card/scan_main_card.dart | 4 +- .../smooth_app/lib/pages/scan/scan_page.dart | 9 +- .../lib/pages/scan/search_page.dart | 2 +- .../user_management/forgot_password_page.dart | 2 +- .../lib/pages/user_management/login_page.dart | 6 +- .../smooth_app/lib/themes/theme_provider.dart | 8 + .../smooth_app/lib/widgets/smooth_text.dart | 9 +- .../lib/widgets/v2/smooth_buttons_bar.dart | 203 ++++++ .../lib/widgets/v2/smooth_scaffold2.dart | 151 +++++ .../lib/widgets/v2/smooth_topbar2.dart | 233 +++++++ 26 files changed, 1680 insertions(+), 419 deletions(-) delete mode 100644 packages/smooth_app/lib/pages/onboarding/country_selector.dart create mode 100644 packages/smooth_app/lib/pages/preferences/country_selector/country_selector.dart create mode 100644 packages/smooth_app/lib/pages/preferences/country_selector/country_selector_provider.dart create mode 100644 packages/smooth_app/lib/widgets/v2/smooth_buttons_bar.dart create mode 100644 packages/smooth_app/lib/widgets/v2/smooth_scaffold2.dart create mode 100644 packages/smooth_app/lib/widgets/v2/smooth_topbar2.dart diff --git a/packages/smooth_app/lib/generic_lib/design_constants.dart b/packages/smooth_app/lib/generic_lib/design_constants.dart index 85efe016209..d9797ea520c 100644 --- a/packages/smooth_app/lib/generic_lib/design_constants.dart +++ b/packages/smooth_app/lib/generic_lib/design_constants.dart @@ -6,6 +6,7 @@ const Widget EMPTY_WIDGET = SizedBox.shrink(); const double VERY_SMALL_SPACE = 4.0; const double SMALL_SPACE = 8.0; +const double BALANCED_SPACE = 10.0; const double MEDIUM_SPACE = 12.0; const double LARGE_SPACE = 16.0; const double VERY_LARGE_SPACE = 20.0; @@ -21,6 +22,12 @@ const Radius ROUNDED_RADIUS = Radius.circular(20.0); //ignore: non_constant_identifier_names const BorderRadius ROUNDED_BORDER_RADIUS = BorderRadius.all(ROUNDED_RADIUS); +/// Topbar… +const Radius HEADER_ROUNDED_RADIUS = Radius.circular(30.0); +//ignore: non_constant_identifier_names +const BorderRadius HEADER_BORDER_RADIUS = + BorderRadius.all(HEADER_ROUNDED_RADIUS); + /// Full screen button, e.g. KnowledgePanel const Radius ANGULAR_RADIUS = Radius.circular(8.0); //ignore: non_constant_identifier_names diff --git a/packages/smooth_app/lib/helpers/provider_helper.dart b/packages/smooth_app/lib/helpers/provider_helper.dart index 3e5753cc5a4..84b86dbc5c5 100644 --- a/packages/smooth_app/lib/helpers/provider_helper.dart +++ b/packages/smooth_app/lib/helpers/provider_helper.dart @@ -39,6 +39,65 @@ class _ListenerState extends SingleChildState> { } } +/// Same as [Listener] but for [ValueNotifier] : notifies when the value changes +class ValueNotifierListener, S> + extends SingleChildStatefulWidget { + const ValueNotifierListener({ + this.listener, + this.listenerWithValueNotifier, + super.key, + super.child, + }) : assert( + listener != null || listenerWithValueNotifier != null, + 'At least one listener must be provided', + ); + + final void Function( + BuildContext context, + S? previousValue, + S currentValue, + )? listener; + + final void Function( + BuildContext context, + T valueNotifier, + S? previousValue, + S currentValue, + )? listenerWithValueNotifier; + + @override + State> createState() => + _ValueNotifierListenerState(); +} + +class _ValueNotifierListenerState, S> + extends SingleChildState> { + S? _oldValue; + + @override + Widget buildWithChild(BuildContext context, Widget? child) { + final S? oldValue = _oldValue; + final T valueNotifier = context.watch(); + final S newValue = valueNotifier.value; + _oldValue = newValue; + + widget.listener?.call( + context, + oldValue, + newValue, + ); + + widget.listenerWithValueNotifier?.call( + context, + valueNotifier, + oldValue, + newValue, + ); + + return child ?? const SizedBox.shrink(); + } +} + /// Same as [Consumer] but only rebuilds if [buildWhen] returns true /// (And on the first build) class ConsumerFilter extends StatefulWidget { @@ -91,6 +150,64 @@ class _ConsumerFilterState extends State> { } } +/// Same as [Consumer] for [ValueNotifier] but only rebuilds if [buildWhen] +/// returns true (and on the first build). +class ConsumerValueNotifierFilter, S> + extends StatefulWidget { + const ConsumerValueNotifierFilter({ + required this.builder, + this.buildWhen, + this.child, + super.key, + }); + + final Widget Function( + BuildContext context, + S value, + Widget? child, + ) builder; + final bool Function(S? previousValue, S currentValue)? buildWhen; + + final Widget? child; + + @override + State> createState() => + _ConsumerValueNotifierFilterState(); +} + +class _ConsumerValueNotifierFilterState, S> + extends State> { + S? oldValue; + Widget? oldWidget; + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, T provider, Widget? child) { + if ((widget.buildWhen != null && + widget.buildWhen!.call(oldValue, provider.value)) || + widget.buildWhen == null && oldValue != provider.value || + oldWidget == null) { + oldWidget = widget.builder( + context, + provider.value, + child, + ); + } + + oldValue = provider.value; + + return widget.builder( + context, + provider.value, + oldWidget, + ); + }, + child: widget.child, + ); + } +} + extension ValueNotifierExtensions on ValueNotifier { void emit(T value) => this.value = value; } diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 72f4d0ceced..4950480c499 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" diff --git a/packages/smooth_app/lib/pages/guides/helpers/guides_content.dart b/packages/smooth_app/lib/pages/guides/helpers/guides_content.dart index 983f588dc27..38fe9a0dfde 100644 --- a/packages/smooth_app/lib/pages/guides/helpers/guides_content.dart +++ b/packages/smooth_app/lib/pages/guides/helpers/guides_content.dart @@ -179,7 +179,7 @@ class _GuidesParagraphTitle extends StatelessWidget { child: Padding( padding: const EdgeInsetsDirectional.symmetric( horizontal: GuidesParagraph._HORIZONTAL_PADDING, - vertical: 10.0, + vertical: BALANCED_SPACE, ), child: Row( crossAxisAlignment: CrossAxisAlignment.baseline, @@ -189,7 +189,7 @@ class _GuidesParagraphTitle extends StatelessWidget { padding: EdgeInsetsDirectional.only(top: 3.3), child: _GuidesParagraphArrow(), ), - const SizedBox(width: 10.0), + const SizedBox(width: BALANCED_SPACE), Expanded( child: Text( title, @@ -244,7 +244,7 @@ class GuidesText extends StatelessWidget { Widget build(BuildContext context) { return Padding( padding: const EdgeInsetsDirectional.only( - top: 10.0, + top: BALANCED_SPACE, start: GuidesParagraph._HORIZONTAL_PADDING, end: GuidesParagraph._HORIZONTAL_PADDING, ), @@ -453,7 +453,7 @@ class GuidesImage extends StatelessWidget { excludeSemantics: true, child: Padding( padding: const EdgeInsetsDirectional.only( - top: 10.0, + top: BALANCED_SPACE, start: GuidesParagraph._HORIZONTAL_PADDING, end: GuidesParagraph._HORIZONTAL_PADDING, ), diff --git a/packages/smooth_app/lib/pages/guides/helpers/guides_footer.dart b/packages/smooth_app/lib/pages/guides/helpers/guides_footer.dart index 1ff923eba8d..494cbe01b87 100644 --- a/packages/smooth_app/lib/pages/guides/helpers/guides_footer.dart +++ b/packages/smooth_app/lib/pages/guides/helpers/guides_footer.dart @@ -34,7 +34,7 @@ class GuidesFooter extends StatelessWidget { top: _FooterPainter.WAVE_SIZE + MEDIUM_SPACE, start: VERY_LARGE_SPACE, end: VERY_LARGE_SPACE, - bottom: 10.0 + MediaQuery.viewPaddingOf(context).bottom, + bottom: BALANCED_SPACE + MediaQuery.viewPaddingOf(context).bottom, ), child: TextButton( style: TextButton.styleFrom( diff --git a/packages/smooth_app/lib/pages/guides/helpers/guides_header.dart b/packages/smooth_app/lib/pages/guides/helpers/guides_header.dart index 9ac100a7827..d52dc3cd4b9 100644 --- a/packages/smooth_app/lib/pages/guides/helpers/guides_header.dart +++ b/packages/smooth_app/lib/pages/guides/helpers/guides_header.dart @@ -33,7 +33,7 @@ class GuidesHeader extends StatelessWidget { style: const TextStyle(color: Colors.white), child: SliverPadding( padding: const EdgeInsetsDirectional.only( - bottom: 10.0, + bottom: BALANCED_SPACE, ), // Pinned = for the header to stay at the top of the screen sliver: SliverPersistentHeader( @@ -79,7 +79,7 @@ class _GuidesHeaderDelegate extends SliverPersistentHeaderDelegate { decoration: ShapeDecoration( shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical( - bottom: Radius.circular(30.0 * (1 - progress)), + bottom: HEADER_ROUNDED_RADIUS * (1 - progress), ), ), color: colors.primaryDark, @@ -113,7 +113,7 @@ class _GuidesHeaderDelegate extends SliverPersistentHeaderDelegate { child: Align( alignment: Alignment.bottomLeft, child: Padding( - padding: const EdgeInsets.only(bottom: 10.0), + padding: const EdgeInsets.only(bottom: BALANCED_SPACE), child: AutoSizeText( title, maxLines: 4, @@ -193,8 +193,8 @@ class _GuidesHeaderLayout extends MultiChildLayoutDelegate { @override void performLayout(Size size) { - final double topMargin = topPadding + 10.0; - final double maxHeight = size.height - topPadding - (10.0 * 2); + final double topMargin = topPadding + BALANCED_SPACE; + final double maxHeight = size.height - topPadding - (BALANCED_SPACE * 2); final Size closeButtonSize = layoutChild( _GuidesHeaderLayoutId.closeButton, @@ -250,7 +250,7 @@ class _GuidesHeaderLayout extends MultiChildLayoutDelegate { positionChild( _GuidesHeaderLayoutId.minimizedTitle, Offset( - _CloseButtonLayout._CLOSE_BUTTON_SIZE + 10.0, + _CloseButtonLayout._CLOSE_BUTTON_SIZE + BALANCED_SPACE, topMargin + 5.0, ), ); @@ -295,7 +295,7 @@ class _BackButton extends StatelessWidget { child: ExcludeSemantics( child: Padding( padding: const EdgeInsetsDirectional.only( - start: 10.0, + start: BALANCED_SPACE, end: 24.0, ), child: Opacity( diff --git a/packages/smooth_app/lib/pages/image_crop_page.dart b/packages/smooth_app/lib/pages/image_crop_page.dart index 67f902807c1..98056485b21 100644 --- a/packages/smooth_app/lib/pages/image_crop_page.dart +++ b/packages/smooth_app/lib/pages/image_crop_page.dart @@ -98,7 +98,7 @@ Future _getUserPictureSource( closeButtonSemanticsOrder: 5.0, body: const _ImageSourcePicker(), bodyPadding: const EdgeInsetsDirectional.only( - start: 10.0, + start: BALANCED_SPACE, end: MEDIUM_SPACE, top: LARGE_SPACE, bottom: MEDIUM_SPACE, @@ -127,7 +127,7 @@ class _ImageSourcePickerState extends State<_ImageSourcePicker> { children: [ IntrinsicHeight( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: BALANCED_SPACE), child: Row( children: [ Expanded( diff --git a/packages/smooth_app/lib/pages/onboarding/country_selector.dart b/packages/smooth_app/lib/pages/onboarding/country_selector.dart deleted file mode 100644 index ebc0d0f6a3d..00000000000 --- a/packages/smooth_app/lib/pages/onboarding/country_selector.dart +++ /dev/null @@ -1,359 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:iso_countries/iso_countries.dart'; -import 'package:openfoodfacts/openfoodfacts.dart'; -import 'package:provider/provider.dart'; -import 'package:smooth_app/data_models/preferences/user_preferences.dart'; -import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; -import 'package:smooth_app/generic_lib/widgets/smooth_text_form_field.dart'; -import 'package:smooth_app/query/product_query.dart'; -import 'package:smooth_app/widgets/smooth_text.dart'; - -/// A selector for selecting user's country. -class CountrySelector extends StatefulWidget { - const CountrySelector({ - this.textStyle, - this.padding, - this.icon, - this.inkWellBorderRadius, - required this.forceCurrencyChange, - }); - - final TextStyle? textStyle; - final EdgeInsetsGeometry? padding; - final BorderRadius? inkWellBorderRadius; - final Widget? icon; - final bool forceCurrencyChange; - - @override - State createState() => _CountrySelectorState(); -} - -class _CountrySelectorState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _countryController = TextEditingController(); - late List _countryList; - - Future _loadLocalizedCountryNames(final String languageCode) async { - List localizedCountries; - - try { - localizedCountries = - await IsoCountries.isoCountriesForLocale(languageCode); - } on MissingPluginException catch (_) { - // Locales are not implemented on desktop and web - // TODO(g123k): Add a complete list - localizedCountries = [ - const Country(name: 'United States', countryCode: 'US'), - const Country(name: 'France', countryCode: 'FR'), - const Country(name: 'Germany', countryCode: 'DE'), - const Country(name: 'India', countryCode: 'IN'), - ]; - } - _countryList = _sanitizeCountriesList(localizedCountries); - } - - @override - Widget build(BuildContext context) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - return Selector( - selector: (BuildContext buildContext, UserPreferences userPreferences) => - userPreferences.appLanguageCode, - builder: (BuildContext context, String? appLanguageCode, _) { - return FutureBuilder( - future: _loadLocalizedCountryNames(appLanguageCode!), - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.hasError) { - return Text('Fatal Error: ${snapshot.error}'); - } else if (snapshot.connectionState != ConnectionState.done) { - return const CircularProgressIndicator.adaptive(); - } - final UserPreferences userPreferences = - context.watch(); - final Country selectedCountry = _getSelectedCountry( - userPreferences.userCountryCode, - ); - final EdgeInsetsGeometry innerPadding = const EdgeInsets.symmetric( - vertical: SMALL_SPACE, - ).add(widget.padding ?? EdgeInsets.zero); - - return InkWell( - borderRadius: widget.inkWellBorderRadius ?? ANGULAR_BORDER_RADIUS, - onTap: () async { - _reorderCountries(selectedCountry); - List filteredList = List.from(_countryList); - final Country? country = await showDialog( - context: context, - builder: (BuildContext context) { - return StatefulBuilder( - builder: (BuildContext context, - void Function(VoidCallback fn) setState) { - const double horizontalPadding = 16.0 + SMALL_SPACE; - - return SmoothListAlertDialog( - title: appLocalizations.country_selector_title, - header: SmoothTextFormField( - type: TextFieldTypes.PLAIN_TEXT, - prefixIcon: const Icon(Icons.search), - controller: _countryController, - onChanged: (String? query) { - query = query!.trim().getComparisonSafeString(); - - setState( - () { - filteredList = _countryList - .where( - (Country item) => - item.name - .getComparisonSafeString() - .contains( - query!, - ) || - item.countryCode - .getComparisonSafeString() - .contains( - query, - ), - ) - .toList(growable: false); - }, - ); - }, - hintText: appLocalizations.search, - ), - scrollController: _scrollController, - list: ListView.separated( - controller: _scrollController, - itemBuilder: (BuildContext context, int index) { - final Country country = filteredList[index]; - final bool selected = country == selectedCountry; - return ListTile( - dense: true, - contentPadding: const EdgeInsets.symmetric( - horizontal: horizontalPadding, - ), - trailing: - selected ? const Icon(Icons.check) : null, - title: TextHighlighter( - text: country.name, - filter: _countryController.text, - selected: selected, - ), - onTap: () { - Navigator.of(context).pop(country); - _countryController.clear(); - }, - ); - }, - separatorBuilder: (_, __) => const Divider( - height: 1.0, - ), - itemCount: filteredList.length, - shrinkWrap: true, - ), - positiveAction: SmoothActionButton( - onPressed: () { - Navigator.pop(context); - _countryController.clear(); - }, - text: appLocalizations.cancel, - ), - ); - }, - ); - }, - ); - if (country != null) { - await ProductQuery.setCountry( - userPreferences, - country.countryCode, - ); - if (context.mounted) { - await _changeCurrencyIfRelevant( - country, - userPreferences, - context, - ); - } - } - }, - child: DecoratedBox( - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - ), - child: IntrinsicHeight( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: innerPadding, - child: const Icon(Icons.public), - ), - Expanded( - flex: 1, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: LARGE_SPACE), - child: Text( - selectedCountry.name, - style: Theme.of(context) - .textTheme - .displaySmall - ?.merge(widget.textStyle), - ), - ), - ), - widget.icon ?? const Icon(Icons.arrow_drop_down), - ], - ), - ), - ), - ); - }, - ); - }, - ); - } - - /// Sanitizes the country list, but without reordering it. - /// - /// * by removing countries that are not in [OpenFoodFactsCountry] - /// * and providing a fallback English name for countries that are in - /// [OpenFoodFactsCountry] but not in [localizedCountries]. - List _sanitizeCountriesList(List localizedCountries) { - final List finalCountriesList = []; - final Map oFFIsoCodeToCountry = - {}; - final Map localizedIsoCodeToCountry = {}; - for (final OpenFoodFactsCountry c in OpenFoodFactsCountry.values) { - oFFIsoCodeToCountry[c.offTag.toLowerCase()] = c; - } - for (final Country c in localizedCountries) { - localizedIsoCodeToCountry.putIfAbsent( - c.countryCode.toLowerCase(), () => c); - } - for (final String countryCode in oFFIsoCodeToCountry.keys) { - final Country? localizedCountry = localizedIsoCodeToCountry[countryCode]; - if (localizedCountry == null) { - // No localization for the country name was found, use English name as - // default. - String countryName = oFFIsoCodeToCountry[countryCode] - .toString() - .replaceAll('OpenFoodFactsCountry.', '') - .replaceAll('_', ' '); - countryName = - '${countryName[0].toUpperCase()}${countryName.substring(1).toLowerCase()}'; - finalCountriesList.add( - Country( - name: _fixCountryName(countryName), - countryCode: _fixCountryCode(countryCode)), - ); - continue; - } - final String fixedCountryCode = _fixCountryCode(countryCode); - final Country country = fixedCountryCode == countryCode - ? localizedCountry - : Country(name: localizedCountry.name, countryCode: countryCode); - finalCountriesList.add(country); - } - return finalCountriesList; - } - - /// Fix the countryCode if needed so Backend can process it. - String _fixCountryCode(String countryCode) { - // 'gb' is handled as 'uk' in the backend. - if (countryCode == 'gb') { - countryCode = 'uk'; - } - return countryCode; - } - - Country _getSelectedCountry(final String? cc) { - if (cc != null) { - for (final Country country in _countryList) { - if (country.countryCode.toLowerCase() == cc.toLowerCase()) { - return country; - } - } - } - return _countryList[0]; - } - - /// Fix the issues where United Kingdom appears with lowercase 'k'. - String _fixCountryName(String countryName) { - if (countryName == 'United kingdom') { - countryName = 'United Kingdom'; - } - return countryName; - } - - /// Reorder countries alphabetically, bring user's locale country to top. - void _reorderCountries(final Country selectedCountry) { - _countryList.sort( - (final Country a, final Country b) { - if (a == selectedCountry) { - return -1; - } - if (b == selectedCountry) { - return 1; - } - return a.name.compareTo(b.name); - }, - ); - } - - @override - void dispose() { - _countryController.dispose(); - super.dispose(); - } - - Future _changeCurrencyIfRelevant( - final Country country, - final UserPreferences userPreferences, - final BuildContext context, - ) async { - final OpenFoodFactsCountry? offCountry = - OpenFoodFactsCountry.fromOffTag(country.countryCode); - final String? possibleCurrencyCode = offCountry?.currency?.name; - if (possibleCurrencyCode == null) { - return; - } - bool? changeCurrency; - final String? currentCurrencyCode = userPreferences.userCurrencyCode; - if (currentCurrencyCode == null) { - changeCurrency = true; - } else if (widget.forceCurrencyChange) { - changeCurrency = true; - } else if (currentCurrencyCode != possibleCurrencyCode) { - final AppLocalizations appLocalizations = AppLocalizations.of(context); - changeCurrency = await showDialog( - context: context, - builder: (final BuildContext context) => SmoothAlertDialog( - body: Text( - '${appLocalizations.country_change_message}' - '\n' - '${appLocalizations.currency_auto_change_message( - currentCurrencyCode, - possibleCurrencyCode, - )}', - ), - negativeAction: SmoothActionButton( - onPressed: () => Navigator.of(context).pop(), - text: appLocalizations.no, - ), - positiveAction: SmoothActionButton( - onPressed: () => Navigator.of(context).pop(true), - text: appLocalizations.yes, - ), - ), - ); - } - if (changeCurrency == true) { - await userPreferences.setUserCurrencyCode(possibleCurrencyCode); - } - } -} diff --git a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart index 736f8ba6425..3aafa112c3b 100644 --- a/packages/smooth_app/lib/pages/onboarding/welcome_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/welcome_page.dart @@ -6,9 +6,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/helpers/app_helper.dart'; -import 'package:smooth_app/pages/onboarding/country_selector.dart'; import 'package:smooth_app/pages/onboarding/next_button.dart'; import 'package:smooth_app/pages/onboarding/onboarding_flow_navigator.dart'; +import 'package:smooth_app/pages/preferences/country_selector/country_selector.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; import 'package:smooth_app/widgets/smooth_scaffold.dart'; import 'package:smooth_app/widgets/smooth_text.dart'; @@ -83,7 +84,7 @@ class WelcomePage extends StatelessWidget { Padding( padding: const EdgeInsets.symmetric( vertical: MEDIUM_SPACE), - child: Ink( + child: Container( decoration: BoxDecoration( border: Border.fromBorderSide( BorderSide( @@ -91,32 +92,27 @@ class WelcomePage extends StatelessWidget { width: 1, ), ), - borderRadius: ROUNDED_BORDER_RADIUS, + borderRadius: ANGULAR_BORDER_RADIUS, color: theme.colorScheme.onPrimary, ), child: SizedBox( width: double.infinity, - child: CountrySelector( - forceCurrencyChange: true, - padding: const EdgeInsets.symmetric( - horizontal: SMALL_SPACE, - ), - inkWellBorderRadius: ROUNDED_BORDER_RADIUS, - icon: Container( - height: double.infinity, - decoration: BoxDecoration( - color: theme.primaryColor, - borderRadius: ROUNDED_BORDER_RADIUS, + child: Material( + type: MaterialType.transparency, + child: CountrySelector( + autoValidate: true, + forceCurrencyChange: true, + padding: const EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: LARGE_SPACE, ), - child: AspectRatio( - aspectRatio: 1.0, - child: Icon( - Icons.edit, - color: Colors.white.withOpacity(0.9), - ), + inkWellBorderRadius: ANGULAR_BORDER_RADIUS, + icon: const icons.Arrow.right( + size: 15.0, ), + textStyle: + TextStyle(color: theme.primaryColor), ), - textStyle: TextStyle(color: theme.primaryColor), ), ), ), diff --git a/packages/smooth_app/lib/pages/preferences/country_selector/country_selector.dart b/packages/smooth_app/lib/pages/preferences/country_selector/country_selector.dart new file mode 100644 index 00000000000..7f6c09cf39e --- /dev/null +++ b/packages/smooth_app/lib/pages/preferences/country_selector/country_selector.dart @@ -0,0 +1,592 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart' hide Listener; +import 'package:flutter/services.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:iso_countries/iso_countries.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:provider/provider.dart'; +import 'package:smooth_app/data_models/preferences/user_preferences.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; +import 'package:smooth_app/generic_lib/duration_constants.dart'; +import 'package:smooth_app/helpers/provider_helper.dart'; +import 'package:smooth_app/pages/prices/emoji_helper.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; +import 'package:smooth_app/widgets/smooth_text.dart'; +import 'package:smooth_app/widgets/v2/smooth_buttons_bar.dart'; +import 'package:smooth_app/widgets/v2/smooth_scaffold2.dart'; +import 'package:smooth_app/widgets/v2/smooth_topbar2.dart'; + +part 'country_selector_provider.dart'; + +/// A button that will open a list of countries and save it in the preferences. +class CountrySelector extends StatelessWidget { + const CountrySelector({ + required this.forceCurrencyChange, + this.textStyle, + this.padding, + this.icon, + this.inkWellBorderRadius, + this.autoValidate = true, + }); + + final TextStyle? textStyle; + final EdgeInsetsGeometry? padding; + final BorderRadius? inkWellBorderRadius; + final Widget? icon; + final bool forceCurrencyChange; + + /// A click on a new country will automatically save it + final bool autoValidate; + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider<_CountrySelectorProvider>( + create: (_) => _CountrySelectorProvider( + preferences: context.read(), + autoValidate: autoValidate, + ), + child: Consumer<_CountrySelectorProvider>( + builder: (BuildContext context, _CountrySelectorProvider provider, _) { + return switch (provider.value) { + _CountrySelectorLoadingState _ => const Center( + child: CircularProgressIndicator.adaptive(), + ), + _CountrySelectorLoadedState _ => _CountrySelectorButton( + icon: icon, + innerPadding: const EdgeInsetsDirectional.symmetric( + vertical: SMALL_SPACE, + ).add(padding ?? EdgeInsets.zero), + textStyle: textStyle, + inkWellBorderRadius: inkWellBorderRadius, + forceCurrencyChange: forceCurrencyChange, + autoValidate: autoValidate, + ), + }; + }, + ), + ); + } +} + +class _CountrySelectorButton extends StatelessWidget { + const _CountrySelectorButton({ + required this.innerPadding, + required this.forceCurrencyChange, + required this.autoValidate, + this.icon, + this.textStyle, + this.inkWellBorderRadius, + }); + + final Widget? icon; + final EdgeInsetsGeometry innerPadding; + final TextStyle? textStyle; + final BorderRadius? inkWellBorderRadius; + final bool forceCurrencyChange; + final bool autoValidate; + + @override + Widget build(BuildContext context) { + return InkWell( + borderRadius: inkWellBorderRadius ?? ANGULAR_BORDER_RADIUS, + onTap: () => _openCountrySelector(context), + child: DecoratedBox( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: ConsumerValueNotifierFilter<_CountrySelectorProvider, + _CountrySelectorState>( + buildWhen: (_CountrySelectorState? previousValue, + _CountrySelectorState currentValue) => + previousValue != null && + currentValue is! _CountrySelectorEditingState && + (currentValue as _CountrySelectorLoadedState).country != + (previousValue as _CountrySelectorLoadedState).country, + builder: (_, _CountrySelectorState value, __) { + final Country? country = + (value as _CountrySelectorLoadedState).country; + + return Padding( + padding: innerPadding, + child: Row( + children: [ + if (country != null) + SizedBox( + width: IconTheme.of(context).size! + LARGE_SPACE, + child: AutoSizeText( + EmojiHelper.getEmojiByCountryCode(country.countryCode)!, + textAlign: TextAlign.center, + style: TextStyle(fontSize: IconTheme.of(context).size), + ), + ) + else + const Icon(Icons.public), + Expanded( + child: Text( + country?.name ?? AppLocalizations.of(context).loading, + style: Theme.of(context) + .textTheme + .displaySmall + ?.merge(textStyle), + ), + ), + icon ?? const Icon(Icons.arrow_drop_down), + ], + ), + ); + }, + ), + ), + ); + } + + Future _openCountrySelector(BuildContext context) async { + final dynamic newCountry = + await Navigator.of(context, rootNavigator: true).push( + PageRouteBuilder( + pageBuilder: (_, __, ___) => + + /// We re-inject the [_CountrySelectorProvider], otherwise it's not in + /// the same tree. [ListenableProvider] allows to prevent the auto-dispose. + ListenableProvider<_CountrySelectorProvider>( + create: (_) => context.read<_CountrySelectorProvider>(), + dispose: (_, __) {}, + child: const _CountrySelectorScreen(), + ), + transitionsBuilder: (BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child) { + final Tween tween = Tween( + begin: const Offset(0.0, 1.0), + end: Offset.zero, + ); + final CurvedAnimation curvedAnimation = CurvedAnimation( + parent: animation, + curve: Curves.easeInOut, + ); + final Animation position = tween.animate(curvedAnimation); + + return SlideTransition( + position: position, + child: FadeTransition( + opacity: animation, + child: child, + ), + ); + }), + ); + + if (!context.mounted) { + return; + } + + /// Ensure to restore the previous state + /// (eg: the user uses the Android back button). + if (newCountry == null) { + context.read<_CountrySelectorProvider>().dismissSelectedCountry(); + } else if (newCountry is Country) { + _changeCurrencyIfRelevant(context, newCountry); + } + } + +// TODO(g123k): move this to a dedicated Provider + Future _changeCurrencyIfRelevant( + final BuildContext context, + final Country country, + ) async { + final UserPreferences userPreferences = context.read(); + final OpenFoodFactsCountry? offCountry = + OpenFoodFactsCountry.fromOffTag(country.countryCode); + final String? possibleCurrencyCode = offCountry?.currency?.name; + + if (possibleCurrencyCode == null) { + return; + } + + bool? changeCurrency; + final String? currentCurrencyCode = userPreferences.userCurrencyCode; + + if (currentCurrencyCode == null) { + changeCurrency = true; + } else if (forceCurrencyChange) { + changeCurrency = true; + } else if (currentCurrencyCode != possibleCurrencyCode) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + changeCurrency = await showDialog( + context: context, + builder: (final BuildContext context) => SmoothAlertDialog( + body: Text( + '${appLocalizations.country_change_message}' + '\n' + '${appLocalizations.currency_auto_change_message( + currentCurrencyCode, + possibleCurrencyCode, + )}', + ), + negativeAction: SmoothActionButton( + onPressed: () => Navigator.of(context, rootNavigator: true).pop(), + text: appLocalizations.no, + ), + positiveAction: SmoothActionButton( + onPressed: () => + Navigator.of(context, rootNavigator: true).pop(true), + text: appLocalizations.yes, + ), + ), + ); + } + if (changeCurrency == true) { + await userPreferences.setUserCurrencyCode(possibleCurrencyCode); + } + } +} + +class _CountrySelectorScreen extends StatelessWidget { + const _CountrySelectorScreen(); + + @override + Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final _CountrySelectorProvider provider = + context.read<_CountrySelectorProvider>(); + + return ValueNotifierListener<_CountrySelectorProvider, + _CountrySelectorState>( + listenerWithValueNotifier: _onValueChanged, + child: ChangeNotifierProvider( + create: (_) => TextEditingController(), + child: SmoothScaffold2( + topBar: SmoothTopBar2( + title: appLocalizations.country_selector_title, + leadingAction: provider.autoValidate + ? SmoothTopBarLeadingAction.minimize + : SmoothTopBarLeadingAction.close, + ), + bottomBar: + !provider.autoValidate ? const _CountrySelectorBottomBar() : null, + injectPaddingInBody: false, + children: const [ + _CountrySelectorSearchBar(), + SliverPadding( + padding: EdgeInsetsDirectional.only( + top: SMALL_SPACE, + ), + ), + _CountrySelectorList() + ], + ), + ), + ); + } + + /// When the value changed in [autoValidate] mode, we close the screen + void _onValueChanged( + BuildContext context, + _CountrySelectorProvider provider, + _CountrySelectorState? oldValue, + _CountrySelectorState currentValue, + ) { + if (provider.autoValidate && + oldValue != null && + currentValue is! _CountrySelectorEditingState && + currentValue is _CountrySelectorLoadedState) { + WidgetsBinding.instance.addPostFrameCallback((_) { + final NavigatorState navigator = Navigator.of(context); + if (navigator.canPop()) { + navigator.pop(currentValue.country); + } + }); + } + } +} + +class _CountrySelectorSearchBar extends StatelessWidget { + const _CountrySelectorSearchBar(); + + @override + Widget build(BuildContext context) { + return SliverPersistentHeader( + pinned: true, + floating: false, + delegate: _CountrySelectorSearchBarDelegate(), + ); + } +} + +class _CountrySelectorSearchBarDelegate extends SliverPersistentHeaderDelegate { + @override + Widget build( + BuildContext context, + double shrinkOffset, + bool overlapsContent, + ) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + final bool darkMode = context.darkTheme(); + + return ColoredBox( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsetsDirectional.only( + top: SMALL_SPACE, + start: SMALL_SPACE, + end: SMALL_SPACE, + ), + child: TextFormField( + controller: context.read(), + textAlignVertical: TextAlignVertical.center, + style: const TextStyle( + fontSize: 15.0, + ), + decoration: InputDecoration( + hintText: AppLocalizations.of(context).search, + enabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(10.0)), + borderSide: BorderSide( + color: colors.primaryNormal, + width: 2.0, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide( + color: darkMode ? colors.primaryNormal : colors.primarySemiDark, + width: 2.0, + ), + ), + contentPadding: const EdgeInsetsDirectional.only( + start: 100, + end: SMALL_SPACE, + top: 10, + bottom: 0, + ), + prefixIcon: icons.Search( + size: 20.0, + color: darkMode ? colors.primaryNormal : colors.primarySemiDark, + ), + ), + ), + ), + ); + } + + @override + double get maxExtent => 48.0; + + @override + double get minExtent => 48.0; + + @override + bool shouldRebuild(covariant _CountrySelectorSearchBarDelegate oldDelegate) => + false; +} + +class _CountrySelectorBottomBar extends StatelessWidget { + const _CountrySelectorBottomBar(); + + @override + Widget build(BuildContext context) { + return ConsumerValueNotifierFilter<_CountrySelectorProvider, + _CountrySelectorState>( + builder: ( + BuildContext context, + _CountrySelectorState value, + _, + ) { + if (value is! _CountrySelectorEditingState) { + return EMPTY_WIDGET; + } + + return SmoothButtonsBar2( + positiveButton: SmoothActionButton2( + text: AppLocalizations.of(context).validate, + icon: const icons.Arrow.right(), + onPressed: () => _saveCountry(context)), + ); + }, + ); + } + + void _saveCountry(BuildContext context) { + final _CountrySelectorProvider countryProvider = + context.read<_CountrySelectorProvider>(); + + /// Without autoValidate, we need to manually close the screen + countryProvider.saveSelectedCountry(); + + if (countryProvider.value is _CountrySelectorEditingState) { + Navigator.of(context).pop( + (countryProvider.value as _CountrySelectorEditingState).selectedCountry, + ); + } + } +} + +class _CountrySelectorList extends StatefulWidget { + const _CountrySelectorList(); + + @override + State<_CountrySelectorList> createState() => _CountrySelectorListState(); +} + +class _CountrySelectorListState extends State<_CountrySelectorList> { + @override + Widget build(BuildContext context) { + return Consumer2<_CountrySelectorProvider, TextEditingController>( + builder: ( + BuildContext context, + _CountrySelectorProvider provider, + TextEditingController controller, + _, + ) { + final _CountrySelectorLoadedState state = + provider.value as _CountrySelectorLoadedState; + final Country? selectedCountry = + state.runtimeType == _CountrySelectorEditingState + ? (state as _CountrySelectorEditingState).selectedCountry + : state.country; + + final Iterable countries = _filterCountries( + state.countries, + state.country, + selectedCountry, + controller.text, + ); + + return SliverFixedExtentList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + final Country country = countries.elementAt(index); + final bool selected = selectedCountry == country; + + return _CountrySelectorListItem( + country: country, + selected: selected, + filter: controller.text, + ); + }, + childCount: countries.length, + addAutomaticKeepAlives: false, + ), + itemExtent: 60.0, + ); + }, + ); + } + + Iterable _filterCountries( + List countries, + Country? userCountry, + Country? selectedCountry, + String? filter, + ) { + if (filter == null || filter.isEmpty) { + return countries; + } + + return countries.where( + (Country country) => + country == userCountry || + country == selectedCountry || + country.name.toLowerCase().contains( + filter.toLowerCase(), + ) || + country.countryCode.toLowerCase().contains( + filter.toLowerCase(), + ), + ); + } +} + +class _CountrySelectorListItem extends StatelessWidget { + const _CountrySelectorListItem({ + required this.country, + required this.selected, + required this.filter, + }); + + final Country country; + final bool selected; + final String filter; + + @override + Widget build(BuildContext context) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + final _CountrySelectorProvider provider = + context.read<_CountrySelectorProvider>(); + + return Semantics( + value: country.name, + button: true, + selected: selected, + excludeSemantics: true, + child: AnimatedContainer( + duration: SmoothAnimationsDuration.short, + margin: const EdgeInsetsDirectional.only( + start: SMALL_SPACE, + end: SMALL_SPACE, + bottom: SMALL_SPACE, + ), + decoration: BoxDecoration( + borderRadius: ANGULAR_BORDER_RADIUS, + border: Border.all( + color: selected ? colors.secondaryLight : colors.primaryMedium, + width: selected ? 3.0 : 1.0, + ), + color: selected + ? context.darkTheme() + ? colors.primarySemiDark + : colors.primaryLight + : Colors.transparent, + ), + child: InkWell( + borderRadius: ANGULAR_BORDER_RADIUS, + onTap: () => provider.changeSelectedCountry(country), + child: Padding( + padding: const EdgeInsetsDirectional.symmetric( + horizontal: SMALL_SPACE, + vertical: VERY_SMALL_SPACE, + ), + child: Row( + children: [ + Expanded( + flex: 1, + child: Text( + EmojiHelper.getEmojiByCountryCode(country.countryCode) ?? + '', + style: const TextStyle(fontSize: 25.0), + ), + ), + Expanded( + flex: 2, + child: Text( + country.countryCode.toUpperCase(), + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + Expanded( + flex: 7, + child: TextHighlighter( + text: country.name, + filter: filter, + textStyle: const TextStyle( + fontWeight: FontWeight.w600, + ), + ), + ) + ], + ), + ), + ), + ), + ); + } +} diff --git a/packages/smooth_app/lib/pages/preferences/country_selector/country_selector_provider.dart b/packages/smooth_app/lib/pages/preferences/country_selector/country_selector_provider.dart new file mode 100644 index 00000000000..f0584570cbb --- /dev/null +++ b/packages/smooth_app/lib/pages/preferences/country_selector/country_selector_provider.dart @@ -0,0 +1,292 @@ +part of 'country_selector.dart'; + +/// A provider with 4 states: +/// * [_CountrySelectorInitialState]: initial state, no countries +/// * [_CountrySelectorLoadingState]: loading countries +/// * [_CountrySelectorLoadedState]: countries loaded and/or saved +/// * [_CountrySelectorEditingState]: the user has selected a country +/// (temporary selection) +class _CountrySelectorProvider extends ValueNotifier<_CountrySelectorState> { + _CountrySelectorProvider({ + required this.preferences, + required this.autoValidate, + }) : super(const _CountrySelectorInitialState()) { + preferences.addListener(_onPreferencesChanged); + _onPreferencesChanged(); + } + + final UserPreferences preferences; + final bool autoValidate; + String? userCountryCode; + String? userAppLanguageCode; + + void changeSelectedCountry(Country country) { + final _CountrySelectorLoadedState state = + value as _CountrySelectorLoadedState; + + value = _CountrySelectorEditingState.fromLoadedState( + loadedState: state, + selectedCountry: country, + ); + + if (autoValidate) { + saveSelectedCountry(); + } + } + + Future saveSelectedCountry() async { + if (value is! _CountrySelectorEditingState) { + return; + } + + /// No need to refresh the state here, the [UserPreferences] will notify + return preferences.setUserCountryCode( + (value as _CountrySelectorEditingState).selectedCountry!.countryCode, + ); + } + + void dismissSelectedCountry() { + if (value is _CountrySelectorEditingState) { + value = (value as _CountrySelectorEditingState).toLoadedState(); + } + } + + Future _onPreferencesChanged() async { + final String? newCountryCode = preferences.userCountryCode; + final String? newAppLanguageCode = preferences.appLanguageCode; + + if (newAppLanguageCode != userAppLanguageCode) { + userAppLanguageCode = newAppLanguageCode; + userCountryCode = newCountryCode; + + return _loadCountries(); + } else if (newCountryCode != userCountryCode) { + userAppLanguageCode = newAppLanguageCode; + userCountryCode = newCountryCode; + + if (value is _CountrySelectorInitialState) { + return _loadCountries(); + } else { + final _CountrySelectorLoadedState state = + value as _CountrySelectorLoadedState; + + /// Reorder items + final List countries = state.countries; + _reorderCountries(countries, userCountryCode); + + value = state.copyWith( + country: _getSelectedCountry(state.countries), + countries: countries, + ); + } + } + } + + Future _loadCountries() async { + if (userAppLanguageCode == null) { + return; + } + + value = const _CountrySelectorLoadingState(); + + List localizedCountries; + + try { + localizedCountries = + await IsoCountries.isoCountriesForLocale(userAppLanguageCode); + } on MissingPluginException catch (_) { + // Locales are not implemented on desktop and web + localizedCountries = [ + const Country(name: 'United States', countryCode: 'US'), + const Country(name: 'France', countryCode: 'FR'), + const Country(name: 'Germany', countryCode: 'DE'), + const Country(name: 'India', countryCode: 'IN'), + ]; + } + + final List countries = await compute( + _reformatCountries, + (localizedCountries, userCountryCode), + ); + + value = _CountrySelectorLoadedState( + country: _getSelectedCountry(countries), + countries: countries, + ); + } + + static Future> _reformatCountries( + (List, String?) localizedCountriesAndUserCountry, + ) async { + final List countries = + _sanitizeCountriesList(localizedCountriesAndUserCountry.$1); + _reorderCountries(countries, localizedCountriesAndUserCountry.$2); + return countries; + } + + /// Sanitizes the country list, but without reordering it. + /// * by removing countries that are not in [OpenFoodFactsCountry] + /// * and providing a fallback English name for countries that are in + /// [OpenFoodFactsCountry] but not in [localizedCountries]. + static List _sanitizeCountriesList( + List localizedCountries) { + final List finalCountriesList = []; + final Map oFFIsoCodeToCountry = + {}; + final Map localizedIsoCodeToCountry = {}; + for (final OpenFoodFactsCountry c in OpenFoodFactsCountry.values) { + oFFIsoCodeToCountry[c.offTag.toLowerCase()] = c; + } + for (final Country c in localizedCountries) { + localizedIsoCodeToCountry.putIfAbsent( + c.countryCode.toLowerCase(), () => c); + } + for (final String countryCode in oFFIsoCodeToCountry.keys) { + final Country? localizedCountry = localizedIsoCodeToCountry[countryCode]; + if (localizedCountry == null) { + // No localization for the country name was found, use English name as + // default. + String countryName = oFFIsoCodeToCountry[countryCode] + .toString() + .replaceAll('OpenFoodFactsCountry.', '') + .replaceAll('_', ' '); + countryName = + '${countryName[0].toUpperCase()}${countryName.substring(1).toLowerCase()}'; + finalCountriesList.add( + Country( + name: _fixCountryName(countryName), + countryCode: _fixCountryCode(countryCode)), + ); + continue; + } + final String fixedCountryCode = _fixCountryCode(countryCode); + final Country country = fixedCountryCode == countryCode + ? localizedCountry + : Country(name: localizedCountry.name, countryCode: countryCode); + finalCountriesList.add(country); + } + + return finalCountriesList; + } + + /// Fix the countryCode if needed so Backend can process it. + static String _fixCountryCode(String countryCode) { + // 'gb' is handled as 'uk' in the backend. + if (countryCode == 'gb') { + countryCode = 'uk'; + } + return countryCode; + } + + /// Fix the issues where United Kingdom appears with lowercase 'k'. + static String _fixCountryName(String countryName) { + if (countryName == 'United kingdom') { + countryName = 'United Kingdom'; + } + return countryName; + } + + /// Reorder countries alphabetically, bring user's locale country to top. + static void _reorderCountries( + List countries, + String? userCountryCode, + ) { + countries.sort( + (final Country a, final Country b) { + if (a.countryCode == userCountryCode) { + return -1; + } + if (b.countryCode == userCountryCode) { + return 1; + } + return a.name.compareTo(b.name); + }, + ); + } + + Country _getSelectedCountry(List countries) { + if (userCountryCode != null) { + for (final Country country in countries) { + if (country.countryCode.toLowerCase() == + userCountryCode?.toLowerCase()) { + return country; + } + } + } + return countries[0]; + } + + @override + void dispose() { + preferences.removeListener(_onPreferencesChanged); + super.dispose(); + } +} + +@immutable +sealed class _CountrySelectorState { + const _CountrySelectorState(); +} + +class _CountrySelectorInitialState extends _CountrySelectorLoadingState { + const _CountrySelectorInitialState(); +} + +class _CountrySelectorLoadingState extends _CountrySelectorState { + const _CountrySelectorLoadingState(); +} + +class _CountrySelectorLoadedState extends _CountrySelectorState { + const _CountrySelectorLoadedState({ + required this.country, + required this.countries, + this.estimatedCountry, + }); + + final Country? country; + final List countries; + + /// We be used later to provide an estimation based on the IP address. + final Country? estimatedCountry; + + _CountrySelectorLoadedState copyWith({ + Country? country, + Country? estimatedCountry, + List? countries, + }) => + _CountrySelectorLoadedState( + country: country ?? this.country, + estimatedCountry: estimatedCountry ?? this.estimatedCountry, + countries: countries ?? this.countries, + ); + + @override + String toString() { + return '_CountrySelectorLoadedState{country: $country, estimatedCountry: $estimatedCountry, countries: $countries}'; + } +} + +class _CountrySelectorEditingState extends _CountrySelectorLoadedState { + _CountrySelectorEditingState.fromLoadedState({ + required this.selectedCountry, + required _CountrySelectorLoadedState loadedState, + }) : super( + country: loadedState.country, + estimatedCountry: loadedState.estimatedCountry, + countries: loadedState.countries, + ); + + final Country? selectedCountry; + + /// Remove the selected country + _CountrySelectorLoadedState toLoadedState() => _CountrySelectorLoadedState( + country: country, + estimatedCountry: estimatedCountry, + countries: countries, + ); + + @override + String toString() { + return '_CountrySelectorEditingState{selectedCountry: $selectedCountry}'; + } +} diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_country_selector.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_country_selector.dart index 6db20531a04..6977710b3d9 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_country_selector.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_country_selector.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; -import 'package:smooth_app/pages/onboarding/country_selector.dart'; +import 'package:smooth_app/pages/preferences/country_selector/country_selector.dart'; import 'package:smooth_app/pages/preferences/user_preferences_item.dart'; class UserPreferencesCountrySelector extends StatelessWidget { @@ -34,6 +34,7 @@ class UserPreferencesCountrySelector extends StatelessWidget { bottom: SMALL_SPACE, ), child: CountrySelector( + autoValidate: false, forceCurrencyChange: false, textStyle: themeData.textTheme.bodyMedium, icon: const Icon(Icons.edit), diff --git a/packages/smooth_app/lib/pages/prices/emoji_helper.dart b/packages/smooth_app/lib/pages/prices/emoji_helper.dart index 77a545b1d9b..5b56715dccf 100644 --- a/packages/smooth_app/lib/pages/prices/emoji_helper.dart +++ b/packages/smooth_app/lib/pages/prices/emoji_helper.dart @@ -2,14 +2,23 @@ import 'package:openfoodfacts/openfoodfacts.dart'; /// Generic helper about emoji display. class EmojiHelper { + const EmojiHelper._(); + /// Returns the country flag emoji. /// /// cf. https://emojipedia.org/flag-italy - String? getCountryEmoji(final OpenFoodFactsCountry? country) { + static String? getCountryEmoji(final OpenFoodFactsCountry? country) { if (country == null) { return null; } - return _getCountryEmojiFromUnicode(country.offTag); + return getEmojiByCountryCode(country.offTag); + } + + static String? getEmojiByCountryCode(final String countryCode) { + if (countryCode.isEmpty) { + return null; + } + return _getCountryEmojiFromUnicode(countryCode); } static const int _emojiCountryLetterA = 0x1F1E6; diff --git a/packages/smooth_app/lib/pages/prices/price_data_widget.dart b/packages/smooth_app/lib/pages/prices/price_data_widget.dart index b246c3d3bb5..a2fea52a97c 100644 --- a/packages/smooth_app/lib/pages/prices/price_data_widget.dart +++ b/packages/smooth_app/lib/pages/prices/price_data_widget.dart @@ -131,7 +131,7 @@ class PriceDataWidget extends StatelessWidget { return null; } final StringBuffer result = StringBuffer(); - final String? countryEmoji = EmojiHelper().getCountryEmoji( + final String? countryEmoji = EmojiHelper.getCountryEmoji( _getCountry(location), ); if (location.name != null) { diff --git a/packages/smooth_app/lib/pages/product/add_new_product_page.dart b/packages/smooth_app/lib/pages/product/add_new_product_page.dart index 2b6aa487e87..92a54dab66f 100644 --- a/packages/smooth_app/lib/pages/product/add_new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/add_new_product_page.dart @@ -318,9 +318,9 @@ class _AddNewProductPageState extends State Widget _backButton() { return Container( margin: const EdgeInsetsDirectional.only( - start: 10.0, - end: 10.0, - top: 10.0, + start: BALANCED_SPACE, + end: BALANCED_SPACE, + top: BALANCED_SPACE, bottom: 0.0, ), width: 20.0, @@ -367,7 +367,7 @@ class _AddNewProductPageState extends State ), ), ), - const SizedBox(width: 10.0), + const SizedBox(width: BALANCED_SPACE), ElevatedButton( style: ElevatedButton.styleFrom( minimumSize: Size(MediaQuery.sizeOf(context).width * 0.35, 40.0), @@ -459,7 +459,10 @@ class _AddNewProductPageState extends State setState(() => _ecoscoreExpanded = !_ecoscoreExpanded); }, child: Container( - padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), + padding: const EdgeInsets.symmetric( + vertical: BALANCED_SPACE, + horizontal: 15.0, + ), decoration: BoxDecoration( borderRadius: ROUNDED_BORDER_RADIUS, color: _colorScheme.surface, @@ -566,7 +569,7 @@ class _AddNewProductPageState extends State rows.add(_buildMainImageButton(context, upToDateProduct, data)); rows.add( const Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), + padding: EdgeInsets.symmetric(vertical: BALANCED_SPACE), child: UserPreferencesListItemDivider(), ), ); diff --git a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart index 6fa71cb85e7..a6e797f0720 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr/edit_ocr_main_action.dart @@ -261,7 +261,7 @@ class _ExtractMainActionProgressIndicator extends StatelessWidget { bottom: SMALL_SPACE, ), child: CupertinoActivityIndicator( - radius: 10.0, + radius: BALANCED_SPACE, color: Colors.white, ), ); diff --git a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart index 26e15c4bf4d..389cc3aa0e6 100644 --- a/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart +++ b/packages/smooth_app/lib/pages/scan/carousel/main_card/scan_main_card.dart @@ -150,7 +150,7 @@ class _SearchBar extends StatelessWidget { child: Padding( padding: const EdgeInsetsDirectional.only( start: 20.0, - end: 10.0, + end: BALANCED_SPACE, bottom: 3.0, ), child: Text( @@ -171,7 +171,7 @@ class _SearchBar extends StatelessWidget { shape: BoxShape.circle, ), child: const Padding( - padding: EdgeInsets.all(10.0), + padding: EdgeInsets.all(BALANCED_SPACE), child: Search( size: 20.0, color: Colors.white, diff --git a/packages/smooth_app/lib/pages/scan/scan_page.dart b/packages/smooth_app/lib/pages/scan/scan_page.dart index 26f22f14e30..a5229d43e1a 100644 --- a/packages/smooth_app/lib/pages/scan/scan_page.dart +++ b/packages/smooth_app/lib/pages/scan/scan_page.dart @@ -91,7 +91,8 @@ class _ScanPageState extends State { Expanded( flex: _carouselHeightPct, child: Padding( - padding: const EdgeInsetsDirectional.only(bottom: 10.0), + padding: const EdgeInsetsDirectional.only( + bottom: BALANCED_SPACE), child: ScanPageCarousel( onPageChangedTo: (int page, String? barcode) async { if (barcode == null) { @@ -185,7 +186,7 @@ class _PermissionDeniedCard extends StatelessWidget { ), child: SmoothCard( padding: const EdgeInsetsDirectional.only( - top: 10.0, + top: BALANCED_SPACE, start: SMALL_SPACE, end: SMALL_SPACE, bottom: 5.0, @@ -206,8 +207,8 @@ class _PermissionDeniedCard extends StatelessWidget { child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric( - horizontal: 10.0, - vertical: 10.0, + horizontal: BALANCED_SPACE, + vertical: BALANCED_SPACE, ), child: Text( localizations.permission_photo_denied_message( diff --git a/packages/smooth_app/lib/pages/scan/search_page.dart b/packages/smooth_app/lib/pages/scan/search_page.dart index f20a0ef87da..68d11d70918 100644 --- a/packages/smooth_app/lib/pages/scan/search_page.dart +++ b/packages/smooth_app/lib/pages/scan/search_page.dart @@ -38,7 +38,7 @@ class _SearchPageState extends State { child: Column( children: [ Padding( - padding: const EdgeInsets.all(10.0), + padding: const EdgeInsets.all(BALANCED_SPACE), child: SearchField( autofocus: widget.autofocus, focusNode: _searchFocusNode, diff --git a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart index 42108e73d1e..ca298f71335 100644 --- a/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart +++ b/packages/smooth_app/lib/pages/user_management/forgot_password_page.dart @@ -109,7 +109,7 @@ class _ForgotPasswordPageState extends State const Spacer(flex: 2), if (_message != '') ...[ SmoothCard( - padding: const EdgeInsets.all(10.0), + padding: const EdgeInsets.all(BALANCED_SPACE), color: _send ? Colors.green : Colors.red, child: Text(_message), ), diff --git a/packages/smooth_app/lib/pages/user_management/login_page.dart b/packages/smooth_app/lib/pages/user_management/login_page.dart index cbda47ad48b..49160ec250f 100644 --- a/packages/smooth_app/lib/pages/user_management/login_page.dart +++ b/packages/smooth_app/lib/pages/user_management/login_page.dart @@ -141,10 +141,10 @@ class _LoginPageState extends State with TraceableClientMixin { _loginResult!.type != LoginResultType.successful) Padding( padding: const EdgeInsets.only( - bottom: 10.0 + LARGE_SPACE * 2, + bottom: BALANCED_SPACE + LARGE_SPACE * 2, ), child: SmoothCard( - padding: const EdgeInsets.all(10.0), + padding: const EdgeInsets.all(BALANCED_SPACE), color: const Color(0xFFEB0004), child: Text( _loginResult!.getErrorMessage(appLocalizations), @@ -251,7 +251,7 @@ class _LoginPageState extends State with TraceableClientMixin { style: ButtonStyle( padding: WidgetStateProperty.all( const EdgeInsets.symmetric( - vertical: 10.0, + vertical: BALANCED_SPACE, horizontal: VERY_LARGE_SPACE, ), ), diff --git a/packages/smooth_app/lib/themes/theme_provider.dart b/packages/smooth_app/lib/themes/theme_provider.dart index 08862fb23ba..6acfd5e4c5f 100644 --- a/packages/smooth_app/lib/themes/theme_provider.dart +++ b/packages/smooth_app/lib/themes/theme_provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:smooth_app/data_models/preferences/user_preferences.dart'; const String THEME_SYSTEM_DEFAULT = 'System Default'; @@ -78,3 +79,10 @@ class ThemeProvider with ChangeNotifier { super.dispose(); } } + +extension ThemeProviderExtension on BuildContext { + bool lightTheme({bool listen = true}) => !darkTheme(listen: listen); + + bool darkTheme({bool listen = true}) => + Provider.of(this, listen: listen).isDarkMode(this); +} diff --git a/packages/smooth_app/lib/widgets/smooth_text.dart b/packages/smooth_app/lib/widgets/smooth_text.dart index bfa2f17066c..dc6efaad081 100644 --- a/packages/smooth_app/lib/widgets/smooth_text.dart +++ b/packages/smooth_app/lib/widgets/smooth_text.dart @@ -66,6 +66,7 @@ class TextHighlighter extends StatelessWidget { this.textAlign, this.selected = false, this.softWrap = false, + this.textStyle, }); final String text; @@ -73,15 +74,17 @@ class TextHighlighter extends StatelessWidget { final TextAlign? textAlign; final bool? softWrap; final bool selected; + final TextStyle? textStyle; @override Widget build(BuildContext context) { List<(String, TextStyle?)> parts; try { + final TextStyle defaultStyle = + textStyle ?? TextStyle(fontWeight: selected ? FontWeight.bold : null); parts = _getParts( - defaultStyle: TextStyle(fontWeight: selected ? FontWeight.bold : null), - highlightedStyle: TextStyle( - fontWeight: selected ? FontWeight.bold : null, + defaultStyle: defaultStyle, + highlightedStyle: defaultStyle.copyWith( backgroundColor: Theme.of(context).primaryColor.withOpacity(0.2), ), ); diff --git a/packages/smooth_app/lib/widgets/v2/smooth_buttons_bar.dart b/packages/smooth_app/lib/widgets/v2/smooth_buttons_bar.dart new file mode 100644 index 00000000000..fb633d808b6 --- /dev/null +++ b/packages/smooth_app/lib/widgets/v2/smooth_buttons_bar.dart @@ -0,0 +1,203 @@ +import 'dart:io'; + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/generic_lib/duration_constants.dart'; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; + +class SmoothButtonsBar2 extends StatefulWidget { + const SmoothButtonsBar2({ + required this.positiveButton, + this.negativeButton, + super.key, + }); + + final SmoothActionButton2 positiveButton; + final SmoothActionButton2? negativeButton; + + @override + State createState() => _SmoothButtonsBar2State(); +} + +class _SmoothButtonsBar2State extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: SmoothAnimationsDuration.brief, + vsync: this, + )..addListener(() => setState(() {})); + + _controller.drive( + Tween( + begin: 0.0, + end: 1.0, + ), + ); + + WidgetsBinding.instance.addPostFrameCallback((_) { + _controller.forward(); + }); + } + + @override + Widget build(BuildContext context) { + final double viewPadding = MediaQuery.viewPaddingOf(context).bottom; + final SmoothColorsThemeExtension? colors = + Theme.of(context).extension(); + + final Widget positiveButtonWidget = + _SmoothPositiveButton2(data: widget.positiveButton); + + final Widget child; + if (widget.negativeButton != null) { + child = Row( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: _SmoothNegativeButton2(data: widget.negativeButton!), + ), + const SizedBox(width: SMALL_SPACE), + Expanded( + child: positiveButtonWidget, + ), + ], + ); + } else { + child = FractionallySizedBox( + widthFactor: 0.75, + child: positiveButtonWidget, + ); + } + + return Opacity( + opacity: _controller.value, + child: Container( + transform: Matrix4.translationValues( + 0.0, + (15.0 + viewPadding + MEDIUM_SPACE + BALANCED_SPACE * 2) * + (1.0 - _controller.value), + 0.0, + ), + width: double.infinity, + decoration: BoxDecoration( + color: + context.darkTheme() ? colors!.primaryDark : colors!.primaryMedium, + boxShadow: [ + BoxShadow( + color: context.darkTheme() ? Colors.white10 : Colors.black12, + blurRadius: 6.0, + offset: const Offset(0.0, -4.0), + ), + ], + ), + padding: EdgeInsetsDirectional.only( + start: BALANCED_SPACE, + end: BALANCED_SPACE, + top: MEDIUM_SPACE, + bottom: _bottomPadding + viewPadding, + ), + child: child, + ), + ); + } + + double get _bottomPadding { + if (Platform.isIOS) { + return 0.0; + } else if (Platform.isAndroid) { + return VERY_SMALL_SPACE; + } else { + return MEDIUM_SPACE; + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } +} + +class SmoothActionButton2 { + SmoothActionButton2({ + required this.text, + required this.onPressed, + this.icon, + }) : assert(text.isNotEmpty); + + final String text; + final Widget? icon; + final VoidCallback? onPressed; +} + +class _SmoothPositiveButton2 extends StatelessWidget { + const _SmoothPositiveButton2({required this.data}); + + final SmoothActionButton2 data; + + @override + Widget build(BuildContext context) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + + return TextButton( + style: TextButton.styleFrom( + backgroundColor: colors.primaryBlack, + foregroundColor: Colors.white, + shape: const RoundedRectangleBorder( + borderRadius: CIRCULAR_BORDER_RADIUS, + ), + padding: const EdgeInsetsDirectional.symmetric( + horizontal: BALANCED_SPACE, + vertical: MEDIUM_SPACE, + ), + ), + onPressed: data.onPressed, + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + textBaseline: TextBaseline.alphabetic, + children: [ + AutoSizeText( + data.text, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15.0, + ), + maxLines: 1, + ), + if (data.icon != null) ...[ + const SizedBox(width: SMALL_SPACE), + Padding( + padding: const EdgeInsetsDirectional.only(top: 0.5), + child: SizedBox( + height: 13.0, + child: FittedBox( + child: data.icon, + ), + ), + ) + ], + ], + ), + ); + } +} + +// TODO(g123k): Not implemented +class _SmoothNegativeButton2 extends StatelessWidget { + const _SmoothNegativeButton2({required this.data}); + + final SmoothActionButton2 data; + + @override + Widget build(BuildContext context) { + throw Exception('Not implemented!'); + } +} diff --git a/packages/smooth_app/lib/widgets/v2/smooth_scaffold2.dart b/packages/smooth_app/lib/widgets/v2/smooth_scaffold2.dart new file mode 100644 index 00000000000..5986bd09c36 --- /dev/null +++ b/packages/smooth_app/lib/widgets/v2/smooth_scaffold2.dart @@ -0,0 +1,151 @@ +import 'package:flutter/material.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/widgets/smooth_scaffold.dart'; +import 'package:smooth_app/widgets/v2/smooth_topbar2.dart'; + +class SmoothScaffold2 extends StatefulWidget { + const SmoothScaffold2({ + required this.children, + this.topBar, + this.bottomBar, + this.injectPaddingInBody = true, + super.key, + }); + + final SmoothTopBar2? topBar; + final List children; + final Widget? bottomBar; + final bool injectPaddingInBody; + + @override + State createState() => _SmoothScaffold2State(); +} + +class _SmoothScaffold2State extends State { + final ScrollController _controller = ScrollController(); + + @override + Widget build(BuildContext context) { + final EdgeInsets viewPadding = MediaQuery.viewPaddingOf(context); + + return SmoothScaffold( + body: PrimaryScrollController( + controller: _controller, + child: CustomMultiChildLayout( + delegate: _SmoothScaffold2Layout( + viewPadding: viewPadding, + injectPaddingInBody: widget.injectPaddingInBody, + ), + children: [ + LayoutId( + id: _SmoothScaffold2Widget.body, + child: CustomScrollView( + controller: _controller, + slivers: [ + if (widget.injectPaddingInBody) + SliverPadding( + padding: EdgeInsetsDirectional.only( + top: widget.topBar != null + ? HEADER_ROUNDED_RADIUS.x + MEDIUM_SPACE + : viewPadding.top, + ), + ), + ...widget.children, + SliverPadding( + padding: EdgeInsetsDirectional.only( + bottom: viewPadding.bottom, + ), + ) + ], + ), + ), + if (widget.topBar != null) + LayoutId( + id: _SmoothScaffold2Widget.topBar, + child: widget.topBar!, + ), + if (widget.bottomBar != null) + LayoutId( + id: _SmoothScaffold2Widget.bottomBar, + child: widget.bottomBar!, + ), + ], + ), + ), + ); + } +} + +enum _SmoothScaffold2Widget { + topBar, + body, + bottomBar, +} + +class _SmoothScaffold2Layout extends MultiChildLayoutDelegate { + _SmoothScaffold2Layout({ + required this.viewPadding, + required this.injectPaddingInBody, + }); + + final EdgeInsets viewPadding; + final bool injectPaddingInBody; + + @override + void performLayout(Size size) { + double topBarHeight; + + // Top bar + if (hasChild(_SmoothScaffold2Widget.topBar)) { + topBarHeight = layoutChild( + _SmoothScaffold2Widget.topBar, + BoxConstraints.loose(size), + ).height; + } else { + topBarHeight = 0.0; + } + + double bottomBarHeight; + + // Top bar + if (hasChild(_SmoothScaffold2Widget.bottomBar)) { + bottomBarHeight = layoutChild( + _SmoothScaffold2Widget.bottomBar, + BoxConstraints.loose( + size, + ), + ).height; + } else { + bottomBarHeight = 0.0; + } + + // Body + final double bodyTopPosition = topBarHeight > 0.0 + ? topBarHeight - (injectPaddingInBody ? HEADER_ROUNDED_RADIUS.x : 0.0) + : 0.0; + layoutChild( + _SmoothScaffold2Widget.body, + BoxConstraints( + minWidth: size.width, + maxWidth: size.width, + minHeight: 0.0, + maxHeight: size.height - bodyTopPosition - bottomBarHeight, + ), + ); + + positionChild(_SmoothScaffold2Widget.body, Offset(0.0, bodyTopPosition)); + + if (topBarHeight > 0.0) { + positionChild(_SmoothScaffold2Widget.topBar, Offset.zero); + } + if (bottomBarHeight > 0.0) { + positionChild( + _SmoothScaffold2Widget.bottomBar, + Offset(0.0, size.height - bottomBarHeight), + ); + } + } + + @override + bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) => false; +} diff --git a/packages/smooth_app/lib/widgets/v2/smooth_topbar2.dart b/packages/smooth_app/lib/widgets/v2/smooth_topbar2.dart new file mode 100644 index 00000000000..6a85406c5d4 --- /dev/null +++ b/packages/smooth_app/lib/widgets/v2/smooth_topbar2.dart @@ -0,0 +1,233 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/helpers/num_utils.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; +import 'package:smooth_app/themes/smooth_theme_colors.dart'; +import 'package:smooth_app/themes/theme_provider.dart'; + +class SmoothTopBar2 extends StatefulWidget { + const SmoothTopBar2({ + required this.title, + this.leadingAction, + this.elevation = 4.0, + super.key, + }) : assert(title.length > 0); + + /// Height without the top view padding + static double kTopBar2Height = 100; + + final String title; + final double elevation; + final SmoothTopBarLeadingAction? leadingAction; + + @override + State createState() => _SmoothTopBar2State(); +} + +class _SmoothTopBar2State extends State { + double _elevation = 0.0; + + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback( + (_) => PrimaryScrollController.maybeOf(context)?.addListener( + () => _onScroll(), + ), + ); + } + + void _onScroll() { + final double offset = PrimaryScrollController.of(context).offset; + final double newElevation = offset.progressAndClamp( + 0.0, + HEADER_ROUNDED_RADIUS.x * 2.0, + 1.0, + ) * + widget.elevation; + + if (newElevation != _elevation) { + setState(() { + _elevation = newElevation; + }); + } + } + + @override + Widget build(BuildContext context) { + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + final TextDirection textDirection = Directionality.of(context); + final bool darkTheme = context.darkTheme(); + + final double imageWidth = MediaQuery.sizeOf(context).width * 0.22; + final double imageHeight = imageWidth * 114 / 92; + + return PhysicalModel( + color: Colors.transparent, + elevation: _elevation, + shadowColor: context.darkTheme() ? Colors.white10 : Colors.black12, + borderRadius: const BorderRadius.vertical( + bottom: HEADER_ROUNDED_RADIUS, + ), + child: ClipRRect( + borderRadius: const BorderRadius.vertical( + bottom: HEADER_ROUNDED_RADIUS, + ), + child: ColoredBox( + color: darkTheme ? colors.primaryDark : colors.primaryMedium, + child: Padding( + padding: EdgeInsetsDirectional.only( + top: MediaQuery.viewPaddingOf(context).top, + ), + child: SizedBox( + height: SmoothTopBar2.kTopBar2Height, + child: Stack( + children: [ + Positioned.directional( + textDirection: textDirection, + bottom: -(imageHeight / 2.1), + end: -imageWidth * 0.15, + child: ExcludeSemantics( + child: SvgPicture.asset( + 'assets/product/product_completed_graphic_light.svg', + width: MediaQuery.sizeOf(context).width * 0.22, + height: imageHeight, + ), + ), + ), + Positioned.directional( + textDirection: textDirection, + top: MEDIUM_SPACE, + bottom: VERY_LARGE_SPACE, + start: widget.leadingAction != null + ? BALANCED_SPACE + : VERY_LARGE_SPACE, + end: imageWidth * 0.7, + child: Align( + alignment: AlignmentDirectional.topStart, + child: Row( + children: [ + if (widget.leadingAction != null) ...[ + _SmoothTopBarLeadingButton( + action: widget.leadingAction!), + const SizedBox(width: BALANCED_SPACE) + ], + Expanded( + child: Padding( + padding: widget.leadingAction != null + ? const EdgeInsets.only(bottom: 1.56) + : EdgeInsets.zero, + child: Text( + widget.title, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: darkTheme + ? colors.primaryMedium + : colors.primaryBlack, + fontSize: 20.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ), + ) + ], + ), + ), + ), + ), + ), + ); + } +} + +enum SmoothTopBarLeadingAction { + close, + back, + minimize, +} + +class _SmoothTopBarLeadingButton extends StatelessWidget { + const _SmoothTopBarLeadingButton({ + required this.action, + }); + + final SmoothTopBarLeadingAction action; + + @override + Widget build(BuildContext context) { + final MaterialLocalizations localizations = + MaterialLocalizations.of(context); + final SmoothColorsThemeExtension colors = + Theme.of(context).extension()!; + + final String message = getMessage(localizations); + final Color color = + context.darkTheme() ? colors.primaryMedium : colors.primaryBlack; + + return Semantics( + button: true, + value: message, + excludeSemantics: true, + child: Tooltip( + message: message, + child: Material( + type: MaterialType.transparency, + child: InkWell( + onTap: () => Navigator.of(context).maybePop(), + customBorder: const CircleBorder(), + splashColor: Colors.white70, + child: Ink( + decoration: BoxDecoration( + border: Border.all( + color: color, + width: 1.0, + ), + shape: BoxShape.circle, + ), + child: SizedBox.square( + dimension: 36.0, + child: appIcon( + size: 16.0, + color: color, + ), + ), + ), + ), + ), + ), + ); + } + + Widget appIcon({ + required double size, + required Color color, + }) { + assert(size >= 0.0); + + return switch (action) { + SmoothTopBarLeadingAction.close => icons.Close(size: size, color: color), + SmoothTopBarLeadingAction.back => + icons.Arrow.left(size: size, color: color), + SmoothTopBarLeadingAction.minimize => Padding( + padding: const EdgeInsetsDirectional.only(top: 1.0), + child: icons.Chevron.down(size: size, color: color), + ), + }; + } + + String getMessage(MaterialLocalizations localizations) { + return switch (action) { + SmoothTopBarLeadingAction.close => localizations.closeButtonTooltip, + SmoothTopBarLeadingAction.back => localizations.backButtonTooltip, + SmoothTopBarLeadingAction.minimize => localizations.closeButtonTooltip, + }; + } +} From cd46675f1f37c0ba3a988232bc1138ebd8ecf843 Mon Sep 17 00:00:00 2001 From: Open Food Facts Bot <119524357+openfoodfacts-bot@users.noreply.github.com> Date: Sun, 21 Jul 2024 13:00:29 +0200 Subject: [PATCH 72/85] chore: New translations to review and merge (#5423) * New translations app_en.arb (Flemish) * New translations app_en.arb (Bosnian) * New translations app_en.arb (Sinhala) * New translations app_en.arb (Cornish) * New translations app_en.arb (Uzbek) * New translations app_en.arb (Kannada) * New translations app_en.arb (Akan) * New translations app_en.arb (Songhay) * New translations app_en.arb (Assamese) * New translations app_en.arb (Scottish Gaelic) * New translations app_en.arb (Wolof) * New translations app_en.arb (Southern Ndebele) * New translations app_en.arb (Walloon) * New translations app_en.arb (Asturian) * New translations app_en.arb (Malagasy) * New translations app_en.arb (Acholi) * New translations app_en.arb (Swahili) * New translations app_en.arb (Odia) * New translations app_en.arb (Norwegian Bokmal) * New translations app_en.arb (Occitan) * New translations app_en.arb (Valencian) * New translations app_en.arb (Serbian (Latin)) * New translations app_en.arb (Amharic) * New translations app_en.arb (Nepali) * New translations app_en.arb (Montenegrin (Cyrillic)) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (Tahitian) * New translations app_en.arb (Hausa) * New translations app_en.arb (Chuvash) * New translations app_en.arb (Berber) * New translations app_en.arb (Scots) * New translations app_en.arb (Tajik) * New translations app_en.arb (Lao) * New translations app_en.arb (Quechua) * New translations app_en.arb (Somali) * New translations app_en.arb (Yoruba) * New translations app_en.arb (Afar) * New translations app_en.arb (Bambara) * New translations app_en.arb (Chechen) * New translations app_en.arb (Cherokee) * New translations app_en.arb (Corsican) * New translations app_en.arb (Haitian Creole) * New translations app_en.arb (Sichuan Yi) * New translations app_en.arb (Inuktitut) * New translations app_en.arb (Javanese) * New translations app_en.arb (Santali) * New translations app_en.arb (Sardinian) * New translations app_en.arb (Sindhi) * New translations app_en.arb (Sango) * New translations app_en.arb (Shona) * New translations app_en.arb (Tigrinya) * New translations app_en.arb (Sanskrit) * New translations app_en.arb (Seychellois Creole) * New translations app_en.arb (Venetian) * New translations app_en.arb (Southern Sami) * New translations app_en.arb (Akan, Twi) * New translations app_en.arb (Talossan) * New translations app_en.arb (Zeelandic) * New translations app_en.arb (Kabyle) * New translations app_en.arb (Urdu (India)) * New translations app_en.arb (LOLCAT) * New translations app_en.arb (Ukrainian) * New translations app_en.arb (Tamil) * New translations app_en.arb (Hebrew) * New translations app_en.arb (German) * New translations app_en.arb (Portuguese) * New translations app_en.arb (Dutch) * New translations app_en.arb (Portuguese) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (Hebrew) * New translations app_en.arb (Thai) * New translations app_en.arb (Finnish) * New translations app_en.arb (Finnish) * New translations app_en.arb (Italian) * New translations app_en.arb (Chinese Simplified) * New translations app_en.arb (Dutch) * New translations app_en.arb (Serbian (Cyrillic)) * New translations app_en.arb (Chinese Traditional) * New translations app_en.arb (Portuguese, Brazilian) * New translations app_en.arb (English, Australia) * New translations app_en.arb (English, United Kingdom) * New translations app_en.arb (Chinese Traditional, Hong Kong) * New translations app_en.arb (Serbian (Latin)) * New translations app_en.arb (Montenegrin (Cyrillic)) * New translations app_en.arb (Dutch, Belgium) * New translations infoplist.strings (Portuguese) * New translations infoplist.strings (Portuguese, Brazilian) * Removing all files with parent folders containing 3 letter lang codes Remove files with parent folders containing 3-letter language codes * Delete `packages/smooth_app/ios/Runner/ach.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/ast.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/ber.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/chr.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/crs.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/fil.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/kab.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/sat.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/sco.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/sma.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/son.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/tzl.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/val.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/vec.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/vls.lproj/InfoPlist.strings` * Delete `packages/smooth_app/ios/Runner/zea.lproj/InfoPlist.strings` --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/openfoodfacts/smooth-app/pull/5423?shareId=654eba10-27cc-4573-81d1-566d37cab1e3). * New translations app_en.arb (French) * New translations app_en.arb (Chinese Simplified) * New translations app_en.arb (Czech) * cleanup * New translations app_en.arb (German) * New translations app_en.arb (Italian) * New translations app_en.arb (Lithuanian) * New translations app_en.arb (Dutch) * New translations app_en.arb (Italian) * New translations app_en.arb (Hebrew) * New translations app_en.arb (Czech) * New translations app_en.arb (Chinese Simplified) * New translations app_en.arb (English) * New translations app_en.arb (German) * New translations app_en.arb (Italian) * New translations app_en.arb (Lithuanian) * New translations app_en.arb (Dutch) * New translations app_en.arb (Hebrew) * New translations app_en.arb (Romanian) * New translations app_en.arb (French) * New translations app_en.arb (Spanish) * New translations app_en.arb (Afrikaans) * New translations app_en.arb (Arabic) * New translations app_en.arb (Belarusian) * New translations app_en.arb (Bulgarian) * New translations app_en.arb (Catalan) * New translations app_en.arb (Danish) * New translations app_en.arb (Greek) * New translations app_en.arb (Basque) * New translations app_en.arb (Finnish) * New translations app_en.arb (Irish) * New translations app_en.arb (Gujarati) * New translations app_en.arb (Hungarian) * New translations app_en.arb (Armenian) * New translations app_en.arb (Japanese) * New translations app_en.arb (Georgian) * New translations app_en.arb (Korean) * New translations app_en.arb (Kurdish) * New translations app_en.arb (Mongolian) * New translations app_en.arb (Norwegian) * New translations app_en.arb (Punjabi) * New translations app_en.arb (Polish) * New translations app_en.arb (Portuguese) * New translations app_en.arb (Russian) * New translations app_en.arb (Slovak) * New translations app_en.arb (Slovenian) * New translations app_en.arb (Albanian) * New translations app_en.arb (Serbian (Cyrillic)) * New translations app_en.arb (Swati) * New translations app_en.arb (Southern Sotho) * New translations app_en.arb (Swedish) * New translations app_en.arb (Tswana) * New translations app_en.arb (Turkish) * New translations app_en.arb (Tsonga) * New translations app_en.arb (Ukrainian) * New translations app_en.arb (Venda) * New translations app_en.arb (Xhosa) * New translations app_en.arb (Chinese Traditional) * New translations app_en.arb (Zulu) * New translations app_en.arb (Vietnamese) * New translations app_en.arb (Galician) * New translations app_en.arb (Icelandic) * New translations app_en.arb (Portuguese, Brazilian) * New translations app_en.arb (Indonesian) * New translations app_en.arb (Persian) * New translations app_en.arb (Khmer) * New translations app_en.arb (Tamil) * New translations app_en.arb (Bengali) * New translations app_en.arb (Marathi) * New translations app_en.arb (Thai) * New translations app_en.arb (Croatian) * New translations app_en.arb (Norwegian Nynorsk) * New translations app_en.arb (Kazakh) * New translations app_en.arb (Estonian) * New translations app_en.arb (Latvian) * New translations app_en.arb (Azerbaijani) * New translations app_en.arb (Hindi) * New translations app_en.arb (Kyrgyz) * New translations app_en.arb (Malay) * New translations app_en.arb (Maori) * New translations app_en.arb (Telugu) * New translations app_en.arb (English, Australia) * New translations app_en.arb (English, United Kingdom) * New translations app_en.arb (Tagalog) * New translations app_en.arb (Burmese) * New translations app_en.arb (Yiddish) * New translations app_en.arb (Maltese) * New translations app_en.arb (Welsh) * New translations app_en.arb (Faroese) * New translations app_en.arb (Esperanto) * New translations app_en.arb (Uyghur) * New translations app_en.arb (Filipino) * New translations app_en.arb (Luxembourgish) * New translations app_en.arb (Chinese Traditional, Hong Kong) * New translations app_en.arb (Tatar) * New translations app_en.arb (Malayalam) * New translations app_en.arb (Breton) * New translations app_en.arb (Romansh) * New translations app_en.arb (Tibetan) * New translations app_en.arb (Latin) * New translations app_en.arb (Flemish) * New translations app_en.arb (Bosnian) * New translations app_en.arb (Sinhala) * New translations app_en.arb (Cornish) * New translations app_en.arb (Uzbek) * New translations app_en.arb (Kannada) * New translations app_en.arb (Akan) * New translations app_en.arb (Songhay) * New translations app_en.arb (Assamese) * New translations app_en.arb (Scottish Gaelic) * New translations app_en.arb (Wolof) * New translations app_en.arb (Southern Ndebele) * New translations app_en.arb (Walloon) * New translations app_en.arb (Asturian) * New translations app_en.arb (Malagasy) * New translations app_en.arb (Acholi) * New translations app_en.arb (Swahili) * New translations app_en.arb (Odia) * New translations app_en.arb (Norwegian Bokmal) * New translations app_en.arb (Occitan) * New translations app_en.arb (Valencian) * New translations app_en.arb (Serbian (Latin)) * New translations app_en.arb (Amharic) * New translations app_en.arb (Nepali) * New translations app_en.arb (Montenegrin (Cyrillic)) * New translations app_en.arb (Dutch, Belgium) * New translations app_en.arb (Tahitian) * New translations app_en.arb (Hausa) * New translations app_en.arb (Chuvash) * New translations app_en.arb (Berber) * New translations app_en.arb (Scots) * New translations app_en.arb (Tajik) * New translations app_en.arb (Lao) * New translations app_en.arb (Quechua) * New translations app_en.arb (Somali) * New translations app_en.arb (Yoruba) * New translations app_en.arb (Afar) * New translations app_en.arb (Bambara) * New translations app_en.arb (Chechen) * New translations app_en.arb (Cherokee) * New translations app_en.arb (Corsican) * New translations app_en.arb (Haitian Creole) * New translations app_en.arb (Sichuan Yi) * New translations app_en.arb (Inuktitut) * New translations app_en.arb (Javanese) * New translations app_en.arb (Santali) * New translations app_en.arb (Sardinian) * New translations app_en.arb (Sindhi) * New translations app_en.arb (Sango) * New translations app_en.arb (Shona) * New translations app_en.arb (Tigrinya) * New translations app_en.arb (Sanskrit) * New translations app_en.arb (Seychellois Creole) * New translations app_en.arb (Venetian) * New translations app_en.arb (Southern Sami) * New translations app_en.arb (Akan, Twi) * New translations app_en.arb (Talossan) * New translations app_en.arb (Zeelandic) * New translations app_en.arb (Kabyle) * New translations app_en.arb (Urdu (India)) * New translations app_en.arb (LOLCAT) * clean --------- Co-authored-by: Pierre Slamich Co-authored-by: Pierre Slamich --- packages/smooth_app/lib/l10n/app_aa.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_af.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ak.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_am.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ar.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_as.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_az.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_be.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_bg.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_bm.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_bn.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_bo.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_br.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_bs.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ca.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ce.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_co.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_cs.arb | 121 ++++++++-- packages/smooth_app/lib/l10n/app_cv.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_cy.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_da.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_de.arb | 109 ++++++++- packages/smooth_app/lib/l10n/app_el.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_eo.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_es.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_et.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_eu.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_fa.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_fi.arb | 303 ++++++++++++++++-------- packages/smooth_app/lib/l10n/app_fo.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_fr.arb | 109 ++++++++- packages/smooth_app/lib/l10n/app_ga.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_gd.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_gl.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_gu.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ha.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_he.arb | 155 +++++++++--- packages/smooth_app/lib/l10n/app_hi.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_hr.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ht.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_hu.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_hy.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_id.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ii.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_is.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_it.arb | 153 +++++++++--- packages/smooth_app/lib/l10n/app_iu.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ja.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_jv.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ka.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_kk.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_km.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_kn.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ko.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ku.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_kw.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ky.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_la.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_lb.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_lo.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_lt.arb | 105 +++++++- packages/smooth_app/lib/l10n/app_lv.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_mg.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_mi.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ml.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_mn.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_mr.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ms.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_mt.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_my.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_nb.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ne.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_nl.arb | 105 +++++++- packages/smooth_app/lib/l10n/app_nn.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_no.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_nr.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_oc.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_or.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_pa.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_pl.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_pt.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_qu.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_rm.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ro.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ru.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sa.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sc.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sd.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sg.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_si.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sk.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sl.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sn.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_so.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sq.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sr.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ss.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_st.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sv.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_sw.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ta.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_te.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_tg.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_th.arb | 105 +++++++- packages/smooth_app/lib/l10n/app_ti.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_tl.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_tn.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_tr.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ts.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_tt.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_tw.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ty.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ug.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_uk.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ur.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_uz.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_ve.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_vi.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_wa.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_wo.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_xh.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_yi.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_yo.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_zh.arb | 103 +++++++- packages/smooth_app/lib/l10n/app_zu.arb | 103 +++++++- 125 files changed, 12419 insertions(+), 794 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_aa.arb b/packages/smooth_app/lib/l10n/app_aa.arb index 4c629c401ac..a858dc90150 100644 --- a/packages/smooth_app/lib/l10n/app_aa.arb +++ b/packages/smooth_app/lib/l10n/app_aa.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_af.arb b/packages/smooth_app/lib/l10n/app_af.arb index 21d0f14f6cb..8f3560347d9 100644 --- a/packages/smooth_app/lib/l10n/app_af.arb +++ b/packages/smooth_app/lib/l10n/app_af.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Neem 'n foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ak.arb b/packages/smooth_app/lib/l10n/app_ak.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_ak.arb +++ b/packages/smooth_app/lib/l10n/app_ak.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_am.arb b/packages/smooth_app/lib/l10n/app_am.arb index 416ed2c77ed..5e051b28f8c 100644 --- a/packages/smooth_app/lib/l10n/app_am.arb +++ b/packages/smooth_app/lib/l10n/app_am.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ar.arb b/packages/smooth_app/lib/l10n/app_ar.arb index 1f9dcc97150..40546085805 100644 --- a/packages/smooth_app/lib/l10n/app_ar.arb +++ b/packages/smooth_app/lib/l10n/app_ar.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "حسناً", "@okay": {}, + "validate": "التحقق", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "إنشاء", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "اطلع على بيانات الطعام ذات الصلة بتفضيلاتك.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "تحديث الصورة", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "تحديث الصورة", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "الحالة", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "معطيات", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "التقاط صورة", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_as.arb b/packages/smooth_app/lib/l10n/app_as.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_as.arb +++ b/packages/smooth_app/lib/l10n/app_as.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_az.arb b/packages/smooth_app/lib/l10n/app_az.arb index 7b7b86c1735..d4284cb8d0e 100644 --- a/packages/smooth_app/lib/l10n/app_az.arb +++ b/packages/smooth_app/lib/l10n/app_az.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Oldu", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_be.arb b/packages/smooth_app/lib/l10n/app_be.arb index f573d468abb..ba8ce480ed5 100644 --- a/packages/smooth_app/lib/l10n/app_be.arb +++ b/packages/smooth_app/lib/l10n/app_be.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Добра", "@okay": {}, + "validate": "Праверыць", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Выбірайце прадукты, карысныя для вас і планеты.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Паглядзіце даныя аб прадуктах, якія адпавядаюць вашым перавагам.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Абнавіць фота", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Абнавіць фота", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Даныя", @@ -2179,7 +2264,11 @@ }, "capture": "Зрабіць здымак", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Сфатаграфаваць", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Выбраць з галерэі", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bg.arb b/packages/smooth_app/lib/l10n/app_bg.arb index 4f79aa0a9fa..5320d612b09 100644 --- a/packages/smooth_app/lib/l10n/app_bg.arb +++ b/packages/smooth_app/lib/l10n/app_bg.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Добре", "@okay": {}, + "validate": "Потвърди", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Създай", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Избери храна, която е полезна за теб и за планетата.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Виж информация за храната, която отговаря на твоите предпочитания.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Обнови снимката", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Обнови снимката", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Статус", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Данни", @@ -2179,7 +2264,11 @@ }, "capture": "Ново заснемане", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Направи снимка", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Избери от галерията", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bm.arb b/packages/smooth_app/lib/l10n/app_bm.arb index 034656adb48..eb8afe7d449 100644 --- a/packages/smooth_app/lib/l10n/app_bm.arb +++ b/packages/smooth_app/lib/l10n/app_bm.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bn.arb b/packages/smooth_app/lib/l10n/app_bn.arb index df9e896913f..6d3c5d03582 100644 --- a/packages/smooth_app/lib/l10n/app_bn.arb +++ b/packages/smooth_app/lib/l10n/app_bn.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "ওকে", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "এমন খাবার বাছাই করুন যা আপনার জন্য ভালো এবং পৃথিবীর জন্যও ভালো।", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "আপনার পছন্দসই খাবার সংশ্লিষ্ট তথ্যাবলি দেখুন।", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "তথ্য", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "একটি ছবি নিন", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bo.arb b/packages/smooth_app/lib/l10n/app_bo.arb index d880cf68188..a04870a85f2 100644 --- a/packages/smooth_app/lib/l10n/app_bo.arb +++ b/packages/smooth_app/lib/l10n/app_bo.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_br.arb b/packages/smooth_app/lib/l10n/app_br.arb index a47c5ccddb6..050cdd513ac 100644 --- a/packages/smooth_app/lib/l10n/app_br.arb +++ b/packages/smooth_app/lib/l10n/app_br.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Krouiñ", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Roadennoù", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tapout ur skeudenn", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_bs.arb b/packages/smooth_app/lib/l10n/app_bs.arb index 9f80e3cf392..7796e6b3686 100644 --- a/packages/smooth_app/lib/l10n/app_bs.arb +++ b/packages/smooth_app/lib/l10n/app_bs.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "U redu", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Birajte hranu koja je dobra za vas i planetu.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Pogledajte podatke o hrani koji su relevantni za vaše preference.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ca.arb b/packages/smooth_app/lib/l10n/app_ca.arb index cd0811b7bed..146dffbc17f 100644 --- a/packages/smooth_app/lib/l10n/app_ca.arb +++ b/packages/smooth_app/lib/l10n/app_ca.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "D'acord", "@okay": {}, + "validate": "Validar", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Crea", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Trieu menjar que sigui bo per a vosaltres i per al planeta.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Consulteu les dades dels aliments rellevants per a les vostres preferències.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Actualitza la foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Actualitza la foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Estat", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Dades", @@ -2179,7 +2264,11 @@ }, "capture": "Nova captura", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Fer una foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Triar de la galeria", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ce.arb b/packages/smooth_app/lib/l10n/app_ce.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_ce.arb +++ b/packages/smooth_app/lib/l10n/app_ce.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_co.arb b/packages/smooth_app/lib/l10n/app_co.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_co.arb +++ b/packages/smooth_app/lib/l10n/app_co.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cs.arb b/packages/smooth_app/lib/l10n/app_cs.arb index aac58d30cc8..90bb6eeb68e 100644 --- a/packages/smooth_app/lib/l10n/app_cs.arb +++ b/packages/smooth_app/lib/l10n/app_cs.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Potvrdit", "@okay": {}, + "validate": "Ověřit", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Vytvořit", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Vyberte si jídlo, které je dobré pro vás i planetu.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Podívejte se na údaje o jídle relevantní pro vaše preference.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Obnovit fotku", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Obnovit fotku", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,20 +1732,45 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Stav", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Zástupce pro aplikaci Ceny na produktové stránce", "prices_app_button": "Přejít do aplikace Ceny", "prices_generic_title": "Ceny", "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", - "prices_add_an_item": "Add an item", + "prices_add_an_item": "Přidat položku", "prices_add_a_price": "Přidat cenu", - "prices_add_a_receipt": "Add a receipt", + "prices_add_a_receipt": "Přidat účtenku", "prices_add_price_tags": "Add price tags", "prices_barcode_search_not_found": "Produkt nebyl nalezen", - "prices_barcode_search_none_yet": "No product yet", - "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_none_yet": "Zatím žádný produkt", + "prices_barcode_search_question": "Chcete vyhledat tento produkt?", "prices_barcode_search_title": "Hledat produkt", - "prices_barcode_search_running": "Looking for {barcode}", + "prices_barcode_search_running": "Hledání {barcode}", "@prices_barcode_search_running": { "description": "Dialog title about barcode look-up", "placeholders": { @@ -1738,8 +1779,20 @@ } } }, - "prices_barcode_reader_action": "Barcode reader", + "prices_barcode_reader_action": "Čtečka čárových kódů", "prices_view_prices": "Zobrazit ceny", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{Zatím žádná cena} =1{Pouze 1 cena} few{Všechny {count} ceny} other{Všech {count} cen}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1823,9 +1907,10 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, - "dev_mode_section_server": "Server configuration", - "dev_mode_section_product_page": "Product page", - "dev_mode_section_ui": "User Interface", + "dev_mode_section_server": "Konfigurace serveru", + "dev_mode_section_news": "Konfigurace poskytovatele zpráv", + "dev_mode_section_product_page": "Stránka produktu", + "dev_mode_section_ui": "Uživatelské rozhraní", "dev_mode_section_data": "Údaje", "dev_mode_section_experimental_features": "Experimental features", "dev_mode_hide_ecoscore_title": "Vyloučit Eco-Score", @@ -2179,7 +2264,11 @@ }, "capture": "Zachytit nový", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Vyfotit", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Vybrat z galerie", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cv.arb b/packages/smooth_app/lib/l10n/app_cv.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_cv.arb +++ b/packages/smooth_app/lib/l10n/app_cv.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_cy.arb b/packages/smooth_app/lib/l10n/app_cy.arb index 1c3b2975c95..bff3117caae 100644 --- a/packages/smooth_app/lib/l10n/app_cy.arb +++ b/packages/smooth_app/lib/l10n/app_cy.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tynnu llun", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_da.arb b/packages/smooth_app/lib/l10n/app_da.arb index 90bc68b80ec..1281993f4c3 100644 --- a/packages/smooth_app/lib/l10n/app_da.arb +++ b/packages/smooth_app/lib/l10n/app_da.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "OK", "@okay": {}, + "validate": "Bekræftelse", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Opret", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Vælg fødevarer, som er gode for dig og planeten.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Se fødevaredata relevante for dine præferencer.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Opfrisk foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Opfrisk foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Stregkodelæser", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Tag et nyt", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tag et billede", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Vælg fra galleri", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_de.arb b/packages/smooth_app/lib/l10n/app_de.arb index 9af6a20011c..d8fafdee4a6 100644 --- a/packages/smooth_app/lib/l10n/app_de.arb +++ b/packages/smooth_app/lib/l10n/app_de.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Bestätigen", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Erstellen", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Wählen Sie die Lebensmittel, die gut für Sie und für den Planeten sind.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Lassen Sie sich die für Ihre Vorlieben relevanten Lebensmitteldaten anzeigen.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Warum wird diese Meldung angezeigt?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Um die Funktion \"Zutaten extrahieren\" nutzen zu können, muss das Foto zunächst hochgeladen werden.\n\nBitte warten Sie ein paar Sekunden oder geben Sie sie manuell ein.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Foto aktualisieren", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Warum wird diese Meldung angezeigt?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "Um die Funktion \"Verpackung extrahieren\" nutzen zu können, muss das Foto zunächst hochgeladen werden.\n\nBitte warten Sie ein paar Sekunden oder geben Sie es manuell ein.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Foto aktualisieren", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,11 +1732,36 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Benutzerdefinierte URL für Nachrichten", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL der JSON-Datei:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Nicht festgelegt", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Letzte Aktualisierung: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Verknüpfung zur Preise-App auf der Produktseite", "prices_app_button": "Zur Preise-App wechseln", "prices_generic_title": "Preise", - "prices_add_n_prices": "{count,plural, one {}=1{Preis hinzufügen} other{{count} Preise hinzufügen}}", - "prices_send_n_prices": "{count,plural, one {}=1{Preis senden} other{{count} Preise senden}}", + "prices_add_n_prices": "{count,plural, =1{Preis hinzufügen} other{{count} Preise hinzufügen}}", + "prices_send_n_prices": "{count,plural, =1{Preis senden} other{{count} Preise senden}}", "prices_add_an_item": "Ein Element hinzufügen", "prices_add_a_price": "Preis hinzufügen", "prices_add_a_receipt": "Beleg hinzufügen", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcodelesegerät", "prices_view_prices": "Preise anzeigen", + "prices_product_accessibility_summary": "{count,plural, =1{1 Preis} other{{count} Preise}} für {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{Noch kein Preis} =1{Nur ein Preis} other{Alle {count} Preise}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,7 +1814,38 @@ } } }, - "prices_proofs_list_length_one_page": "{count,plural, one {}=0{Noch kein Nachweis} =1{Nur ein Nachweis} other{Alle {count} Nachweise}}", + "prices_entry_accessibility_label": "Preis: {price} / Laden: „{location}” / Veröffentlicht am {date} von „{user}”", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Nachweise von „{user}” öffnen", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Preisnachweis öffnen", + "@prices_open_proof": { + "description": "Button to open a proof" + }, + "prices_proofs_list_length_one_page": "{count,plural, =0{Noch kein Nachweis} =1{Nur ein Nachweis} other{Alle {count} Nachweise}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", "placeholders": { @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Serverkonfiguration", + "dev_mode_section_news": "Konfiguration des Nachrichtenanbieters", "dev_mode_section_product_page": "Produktseite", "dev_mode_section_ui": "Benutzeroberfläche", "dev_mode_section_data": "Daten", @@ -2179,7 +2264,11 @@ }, "capture": "Neu erfassen", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Foto aufnehmen", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Aus Galerie wählen", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Vorschau", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Klicken Sie hier, um uns Ihr Feedback zu dieser neuen Funktion zu senden!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_el.arb b/packages/smooth_app/lib/l10n/app_el.arb index 5a60a511338..286b18ab677 100644 --- a/packages/smooth_app/lib/l10n/app_el.arb +++ b/packages/smooth_app/lib/l10n/app_el.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Εντάξει", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Δημιουργία", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Επιλέξτε τροφές που κάνουν καλό σε εσάς και τον πλανήτη.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Δείτε τα δεδομένα τροφίμων που σχετίζονται με τις προτιμήσεις σας.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Ανανέωση φωτογραφίας", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Ανανέωση φωτογραφίας", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Δεδομένα", @@ -2179,7 +2264,11 @@ }, "capture": "Λήψη νέας", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Τραβήξτε μια φωτογραφία", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Επιλέξτε από τη συλλογή", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eo.arb b/packages/smooth_app/lib/l10n/app_eo.arb index 4b83b9f54aa..790a2629357 100644 --- a/packages/smooth_app/lib/l10n/app_eo.arb +++ b/packages/smooth_app/lib/l10n/app_eo.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_es.arb b/packages/smooth_app/lib/l10n/app_es.arb index 83aba39111e..146258fc1de 100644 --- a/packages/smooth_app/lib/l10n/app_es.arb +++ b/packages/smooth_app/lib/l10n/app_es.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Vale", "@okay": {}, + "validate": "Validar", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Crear", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Elige alimentos que sean buenos para ti y para el planeta.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Consulta los datos de los alimentos relacionados con tus preferencias.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Actualizar foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Actualizar foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Estado", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Acceso directo a la aplicación Prices en la página del producto", "prices_app_button": "Ir a la aplicación Prices", "prices_generic_title": "Precios", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Datos", @@ -2179,7 +2264,11 @@ }, "capture": "Nueva captura", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Saca una foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Seleccionar de la galería", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_et.arb b/packages/smooth_app/lib/l10n/app_et.arb index 050e4ce7d3c..2970c50a16d 100644 --- a/packages/smooth_app/lib/l10n/app_et.arb +++ b/packages/smooth_app/lib/l10n/app_et.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ok", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Loo", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Andmed", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tehke foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_eu.arb b/packages/smooth_app/lib/l10n/app_eu.arb index 594021bf777..9cd75499e14 100644 --- a/packages/smooth_app/lib/l10n/app_eu.arb +++ b/packages/smooth_app/lib/l10n/app_eu.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ados", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Sortu", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Aukeratu zuretzat eta planetarentzako elikagai egokiak.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Zure lehentasunekin bat datozen elikagaien datuak ikusi.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Prezioak aplikazioko produktuaren orrirako laster-bidea", "prices_app_button": "Joan Prezioak aplikaziora", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Datuak", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Atera argazki bat", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fa.arb b/packages/smooth_app/lib/l10n/app_fa.arb index 389afe3a5b9..f1ce484d3af 100644 --- a/packages/smooth_app/lib/l10n/app_fa.arb +++ b/packages/smooth_app/lib/l10n/app_fa.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "باشه", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "یک عکس بگیرید", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fi.arb b/packages/smooth_app/lib/l10n/app_fi.arb index 26cf7e07dbf..f237ab1ad1c 100644 --- a/packages/smooth_app/lib/l10n/app_fi.arb +++ b/packages/smooth_app/lib/l10n/app_fi.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okei", "@okay": {}, + "validate": "Vahvista", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Luo", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Valitse ruoka, joka tekee hyvää sinulle ja planeetalle.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Katso valintoihisi liittyvät ruokatietosi.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -566,7 +566,7 @@ "@new_product_dialog_description": { "description": "Please keep it short, like less than 100 characters. Explanatory text of the dialog when the user searched for an unknown barcode." }, - "new_product_dialog_illustration_description": "An illustration with unknown Nutri-Score and Eco-Score", + "new_product_dialog_illustration_description": "Kuva tuntemattomilla Nutri-Score- ja Eco-Score-pisteillä", "@new_product_dialog_illustration_description": { "description": "A description for accessibility of two images side by side: a Nutri-Score and an EcoScore." }, @@ -740,7 +740,7 @@ "@view_more_photo_button": {}, "no_product_found": "Tuotetta ei löytynyt", "@no_product_found": {}, - "no_location_found": "No location found", + "no_location_found": "Sijaintia ei löytynyt", "not_found": "ei löytynyt:", "refreshing_product": "Päivitetään tuotetta", "@refreshing_product": { @@ -750,7 +750,7 @@ "@product_refreshed": { "description": "Confirmation, that the product data refresh is done" }, - "product_image_accessibility_label": "Image taken on {date}", + "product_image_accessibility_label": "Kuva otettu {date}", "@product_image_accessibility_label": { "placeholders": { "date": { @@ -759,7 +759,7 @@ } } }, - "product_image_outdated_accessibility_label": "Image taken on {date}. This image may be outdated", + "product_image_outdated_accessibility_label": "Kuva otettu {date}. Tämä kuva saattaa olla vanhentunut", "@product_image_outdated_accessibility_label": { "placeholders": { "date": { @@ -768,20 +768,20 @@ } } }, - "homepage_main_card_logo_description": "Welcome to Open Food Facts", + "homepage_main_card_logo_description": "Tervetuloa Open Food Factsiin", "@homepage_main_card_logo_description": { "description": "Description for accessibility of the Open Food Facts logo on the homepage" }, - "homepage_main_card_subheading": "**Scan** a barcode or\n**search** for a product", + "homepage_main_card_subheading": "**Skannaa** viivakoodi tai\n**hae** tuotetta", "@homepage_main_card_subheading": { "description": "Text between asterisks (eg: **My Text**) means text in bold. Please keep it." }, "homepage_main_card_search_field_hint": "Etsi tuote", - "homepage_main_card_search_field_tooltip": "Start search", + "homepage_main_card_search_field_tooltip": "Aloita haku", "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, - "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "scan_tagline_news_item_accessibility": "Viimeisimmät uutiset: {news_title}", "@scan_tagline_news_item_accessibility": { "description": "Accessibility label for the title of a news", "placeholders": { @@ -794,7 +794,7 @@ "tagline_app_review_button_positive": "Rakastan sitä! 😍", "tagline_app_review_button_negative": "En juurikaan…", "tagline_app_review_button_later": "Kysy myöhemmin", - "tagline_feed_news_button": "Know more", + "tagline_feed_news_button": "Lisätietoja", "app_review_negative_modal_title": "Etkö pidä sovelluksestamme?", "app_review_negative_modal_text": "Voisitko käyttää muutaman sekunnin kertoaksesi meille miksi?", "app_review_negative_modal_positive_button": "Kyllä, ehdottomasti!", @@ -803,8 +803,8 @@ "@could_not_refresh": { "description": "The product data couldn't be refreshed" }, - "product_internet_error_modal_title": "An error has occurred!", - "product_internet_error_modal_message": "We are unable to fetch information about this product due to a network error. Please check your internet connection and try again.\n\nInternal error:\n{error}", + "product_internet_error_modal_title": "Tapahtui virhe!", + "product_internet_error_modal_message": "Emme voi noutaa tietoja tästä tuotteesta verkkovirheen vuoksi. Tarkista internet-yhteytesi ja yritä uudelleen.\n\nSisäinen virhe:\n{error}", "@product_internet_error_modal_message": { "placeholders": { "error": { @@ -857,11 +857,11 @@ "@currency_chooser_label": { "description": "Label shown above a selector where the user can select their currency (in the preferences)" }, - "country_change_message": "You have just changed countries.", + "country_change_message": "Olet juuri vaihtanut maata.", "@country_change_message": { "description": "Message stating the change of countries" }, - "currency_auto_change_message": "Do you want to change the currency from {previousCurrency} to {possibleCurrency}?", + "currency_auto_change_message": "Haluatko vaihtaa valuutan {previousCurrency} arvoon {possibleCurrency}?", "@currency_auto_change_message": { "description": "Message asking to confirm the change of currencies", "placeholders": { @@ -1119,8 +1119,8 @@ } } }, - "onboarding_home_welcome_text1": "Welcome !", - "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "onboarding_home_welcome_text1": "Tervetuloa !", + "onboarding_home_welcome_text2": "Sovellus, joka auttaa sinua valitsemaan ruokaa, joka sopii **sinulle** ja **planeetalle**!", "@onboarding_home_welcome_text2": { "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, @@ -1235,7 +1235,7 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, - "camera_window_accessibility_label": "Scan a barcode with your camera", + "camera_window_accessibility_label": "Skannaa viivakoodi kamerallasi", "@camera_window_accessibility_label": { "description": "Accessibility label for the camera window" }, @@ -1479,34 +1479,50 @@ "completed_basic_details_btn_text": "Täytä perustiedot", "not_implemented_snackbar_text": "Ei vielä käytössä", "category_picker_page_appbar_text": "Tuoteluokat", - "edit_ingredients_extract_ingredients_btn_text": "Extract ingredients from the photo", + "edit_ingredients_extract_ingredients_btn_text": "Poimi ainesosat valokuvasta", "@edit_ingredients_extract_ingredients_btn_text": { "description": "Ingredients edition - Extract ingredients" }, - "edit_ingredients_extracting_ingredients_btn_text": "Extracting ingredients\nfrom the photo", + "edit_ingredients_extracting_ingredients_btn_text": "Poimitaan ainesosia\nkuvasta", "@edit_ingredients_extracting_ingredients_btn_text": { "description": "Ingredients edition - Extracting ingredients" }, - "edit_ingredients_loading_photo_btn_text": "Loading photo…", + "edit_ingredients_loading_photo_btn_text": "Ladataan kuvaa…", "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Miksi näen tämän viestin?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Jotta voit käyttää \"Ota ainesosat\" -ominaisuutta, valokuva on ensin ladattava.\n\nOdota muutama sekunti tai kirjoita ne manuaalisesti.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Päivitä kuva", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" }, - "edit_packaging_extract_btn_text": "Extract packaging\nfrom the photo", + "edit_packaging_extract_btn_text": "Poimi pakkaus\nvalokuvasta", "@edit_packaging_extract_btn_text": { "description": "Packaging edition - OCR-Extract packaging" }, - "edit_packaging_extracting_btn_text": "Extracting packaging from the photo", + "edit_packaging_extracting_btn_text": "Poimitaan pakkausta kuvasta", "@edit_packaging_extracting_btn_text": { "description": "Packaging edition - OCR-Extracting packaging" }, - "edit_packaging_loading_photo_btn_text": "Loading photo…", + "edit_packaging_loading_photo_btn_text": "Ladataan kuvaa…", "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Miksi näen tämän viestin?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "Jotta voit käyttää \"Ota pakkaus\" -ominaisuutta, valokuva on ensin ladattava.\n\nOdota muutama sekunti tai kirjoita ne manuaalisesti.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Päivitä kuva", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,20 +1732,45 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Muokattu URL-osoite uutisille", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "JSON-tiedoston URL-osoite:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Ei määritetty", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Tila", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Viimeisin päivitys: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Pikakuvake Hinnat-sovellukseen tuotesivulla", "prices_app_button": "Siirry Hinnat-sovellukseen", "prices_generic_title": "Hinnat", - "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", - "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", - "prices_add_an_item": "Add an item", + "prices_add_n_prices": "{count,plural, =1{Lisää hinta} other{Lisää {count} hintaa}}", + "prices_send_n_prices": "{count,plural, =1{Lähetä hinta} other{Lähetä {count} hintaa}}", + "prices_add_an_item": "Lisää tuote", "prices_add_a_price": "Lisää hinta", - "prices_add_a_receipt": "Add a receipt", - "prices_add_price_tags": "Add price tags", + "prices_add_a_receipt": "Lisää kuitti", + "prices_add_price_tags": "Lisää hintalaput", "prices_barcode_search_not_found": "Tuotetta ei löytynyt", - "prices_barcode_search_none_yet": "No product yet", - "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_none_yet": "Ei tuotetta vielä", + "prices_barcode_search_question": "Haluatko etsiä tätä tuotetta?", "prices_barcode_search_title": "Tuotehaku", - "prices_barcode_search_running": "Looking for {barcode}", + "prices_barcode_search_running": "Etsitään {barcode}", "@prices_barcode_search_running": { "description": "Dialog title about barcode look-up", "placeholders": { @@ -1738,9 +1779,21 @@ } } }, - "prices_barcode_reader_action": "Barcode reader", - "prices_view_prices": "View the prices", - "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", + "prices_barcode_reader_action": "Viivakoodinlukija", + "prices_view_prices": "Katso hinnat", + "prices_product_accessibility_summary": "{count,plural, =1{1 hinta} other{{count} hintaa}} tuotteelle {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, + "prices_list_length_one_page": "{count,plural, =0{Ei hintaa vielä} =1{Vain yksi hinta} other{Kaikki {count} hintaa}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", "placeholders": { @@ -1749,7 +1802,7 @@ } } }, - "prices_list_length_many_pages": "Latest {pageSize} prices (total: {total})", + "prices_list_length_many_pages": "Viimeisimmät {pageSize} hinnat (yhteensä: {total})", "@prices_list_length_many_pages": { "description": "Number of prices for one-page result", "placeholders": { @@ -1761,7 +1814,38 @@ } } }, - "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", + "prices_entry_accessibility_label": "Hinta: {price} / Kauppa: \"{location}\" / tekijän \"{user}\" päivämääränä {date} julkaisema", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Avaa käyttäjän \"{user}\" todisteet", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Avaa hintatodiste", + "@prices_open_proof": { + "description": "Button to open a proof" + }, + "prices_proofs_list_length_one_page": "{count,plural, =0{Ei vielä todisteita} =1{Vain yksi todiste} other{Kaikki {count} todistetta}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", "placeholders": { @@ -1770,7 +1854,7 @@ } } }, - "prices_proofs_list_length_many_pages": "Latest {pageSize} proofs (total: {total})", + "prices_proofs_list_length_many_pages": "Viimeisimmät {pageSize} todisteet (yhteensä: {total})", "@prices_proofs_list_length_many_pages": { "description": "Number of proofs for one-page result", "placeholders": { @@ -1782,7 +1866,7 @@ } } }, - "prices_users_list_length_many_pages": "Top {pageSize} contributors (total: {total})", + "prices_users_list_length_many_pages": "Parhaat {pageSize} avustajat (yhteensä: {total})", "@prices_users_list_length_many_pages": { "description": "Number of users for one-page result", "placeholders": { @@ -1794,27 +1878,27 @@ } } }, - "prices_amount_subtitle": "Amount", - "prices_amount_is_discounted": "Is discounted?", + "prices_amount_subtitle": "Määrä", + "prices_amount_is_discounted": "Onko alennettu?", "prices_amount_price_normal": "Hinta", "prices_amount_price_discounted": "Alennettu hinta", - "prices_amount_price_not_discounted": "Original price", - "prices_amount_no_product": "One product is missing!", - "prices_amount_price_incorrect": "Incorrect value", - "prices_amount_price_mandatory": "Mandatory value", + "prices_amount_price_not_discounted": "Alkuperäinen hinta", + "prices_amount_no_product": "Yksi tuote puuttuu!", + "prices_amount_price_incorrect": "Virheellinen arvo", + "prices_amount_price_mandatory": "Pakollinen arvo", "prices_currency_subtitle": "Valuutta", "prices_date_subtitle": "Päivämäärä", - "prices_location_subtitle": "Shop", - "prices_location_find": "Find a shop", - "prices_location_mandatory": "You need to select a shop!", + "prices_location_subtitle": "Myymälä", + "prices_location_find": "Etsi kauppa", + "prices_location_mandatory": "Sinun on valittava kauppa!", "prices_proof_subtitle": "Todiste", - "prices_proof_find": "Select a proof", + "prices_proof_find": "Valitse todiste", "prices_proof_receipt": "Kuitti", "prices_proof_price_tag": "Hintalappu", - "prices_proof_mandatory": "You need to select a proof!", - "prices_add_validation_error": "Validation error", - "prices_privacy_warning_title": "Privacy warning", - "prices_privacy_warning_message": "Prices will be public, along with the store they refer to.\nThat might allow people who know about your Open Food Facts pseudonym to:\n* infer in which area you live\n* know what you are buying\nIf you are uneasy with that, please change your pseudonym, or create a new Open Food Facts account and log into the app with it.", + "prices_proof_mandatory": "Sinun on valittava todiste!", + "prices_add_validation_error": "Tarkistusvirhe", + "prices_privacy_warning_title": "Tietosuojavaroitus", + "prices_privacy_warning_message": "Hinnat ovat julkisia yhdessä kaupan kanssa, johon ne viittaavat.\nSe saattaa antaa ihmisille, jotka tietävät Open Food Facts -pseudonyymistäsi, mahdollisuuden:\n* päätellä, missä asut\n* tietää mitä ostat\nJos et ole tyytyväinen siihen, vaihda pseudonyymisi tai luo uusi Open Food Facts -tili ja kirjaudu sovellukseen sillä.", "prices_unknown_product": "Tuntematon tuote", "@prices_unknown_product": { "description": "Very small text, in the context of prices, to say that the product is unknown" @@ -1823,20 +1907,21 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, - "dev_mode_section_server": "Server configuration", - "dev_mode_section_product_page": "Product page", - "dev_mode_section_ui": "User Interface", + "dev_mode_section_server": "Palvelimen asetukset", + "dev_mode_section_news": "Uutispalveluntarjoajan määritykset", + "dev_mode_section_product_page": "Tuotesivu", + "dev_mode_section_ui": "Käyttöliittymä", "dev_mode_section_data": "Tiedot", - "dev_mode_section_experimental_features": "Experimental features", + "dev_mode_section_experimental_features": "Kokeelliset ominaisuudet", "dev_mode_hide_ecoscore_title": "Jätä ympäristöystävällisyyspisteytys huomiotta", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, - "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "dev_mode_spellchecker_for_ocr_title": "Käytä OCR-näytöissä oikeinkirjoituksen tarkistusta", "@dev_mode_spellchecker_for_ocr_title": { "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" }, - "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "dev_mode_spellchecker_for_ocr_subtitle": "(Ainesosat ja pakkaus)", "@dev_mode_spellchecker_for_ocr_subtitle": { "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" }, @@ -1899,27 +1984,27 @@ "@user_search_proofs_title": { "description": "User proofs: list tile title" }, - "user_search_proof_title": "My proof", + "user_search_proof_title": "Minun todisteeni", "@user_search_proof_title": { "description": "User proof: page title" }, - "user_any_search_prices_title": "Contributor prices", + "user_any_search_prices_title": "Osallistujien hinnat", "@user_any_search_prices_title": { "description": "User prices (everybody except me): list tile title" }, - "all_search_prices_latest_title": "Latest Prices added", + "all_search_prices_latest_title": "Viimeisimmät hinnat lisätty", "@all_search_prices_latest_title": { "description": "Latest prices: list tile title" }, - "all_search_prices_top_user_title": "Top price contributors", + "all_search_prices_top_user_title": "Hintojen huippuavustajat", "@all_search_prices_top_user_title": { "description": "Top price users: list tile title" }, - "all_search_prices_top_location_title": "Stores with the most prices", + "all_search_prices_top_location_title": "Kaupat, joilla on eniten hintoja", "@all_search_prices_top_location_title": { "description": "Top price locations: list tile title" }, - "all_search_prices_top_product_title": "Products with the most prices", + "all_search_prices_top_product_title": "Tuotteet, joilla on eniten hintoja", "@all_search_prices_top_product_title": { "description": "Top price products: list tile title" }, @@ -2179,7 +2264,11 @@ }, "capture": "Ota uusi", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ota kuva", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Valitse kuvagalleriasta", "@choose_from_gallery": { @@ -2189,7 +2278,7 @@ "@image_upload_queued": { "description": "Message when a photo is queued for upload" }, - "add_price_queued": "The price will be sent to the server as soon as possible.", + "add_price_queued": "Hinta lähetetään palvelimelle mahdollisimman pian.", "@add_price_queued": { "description": "Message when an added price is queued for the server" }, @@ -2737,7 +2826,7 @@ "nutriscore_c": "Nutri-Score C", "nutriscore_d": "Nutri-Score D", "nutriscore_e": "Nutri-Score E", - "nutriscore_new_formula": "Nutri-Score {letter} (New calculation)", + "nutriscore_new_formula": "Nutri-Score {letter} (Uusi laskukaava)", "@nutriscore_new_formula": { "description": "A generic string to define a Nutri-Score V2 with a letter [eg: \"Nutri-Score A (New calculation)\"]", "placeholders": { @@ -2746,11 +2835,11 @@ } } }, - "nutriscore_new_formula_title": "Nutri-Score (New calculation)", + "nutriscore_new_formula_title": "Nutri-Score (Uusi laskukaava)", "nutriscore_unknown": "Tuntematon Nutri-Score", - "nutriscore_unknown_new_formula": "Unknown Nutri-Score (New calculation)", + "nutriscore_unknown_new_formula": "Tuntematon Nutri-Score (Uusi laskukaava)", "nutriscore_not_applicable": "Nutri-Score ei sovellu", - "nutriscore_not_applicable_new_formula": "Nutri-Score is not applicable (New calculation)", + "nutriscore_not_applicable_new_formula": "Nutri-Score ei ole sovellettavissa (Uusi laskukaava)", "ecoscore_generic": "Eco-Score", "ecoscore_a": "Eco-Score A", "ecoscore_b": "Eco-Score B", @@ -2771,7 +2860,7 @@ "faq_title_install_beauty": "Luo kosmeettinen tietokanta asentamalla Open Beauty Facts", "faq_title_install_pet": "Luo lemmikkieläinten ruokatietokanta asentamalla Open Pet Food Facts", "faq_title_install_product": "Asenna Open Products Facts luodaksesi tuotetietokannan objektien käyttöiän pidentämiseksi", - "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", + "faq_nutriscore_nutriscore": "Uusi Nutri-Score-laskukaava: mitä uutta?", "contact_title_pro_page": "Pro? Tuo tuotteesi Open Food Factsiin", "contact_title_pro_email": "Tuottajan yhteystiedot", "contact_title_press_page": "Lehdistösivu", @@ -2789,7 +2878,7 @@ "@link_cant_be_opened": { "description": "An error may happen if the device doesn't have a browser installed." }, - "knowledge_panel_page_title_no_title": "Details for {productName}", + "knowledge_panel_page_title_no_title": "Yksityiskohdat tuotteelle {productName}", "@knowledge_panel_page_title_no_title": { "description": "The title of the page when we click on an item in the product page and this page is unnamed", "placeholders": { @@ -2798,7 +2887,7 @@ } } }, - "knowledge_panel_page_title": "Details for {pageName} with {productName}", + "knowledge_panel_page_title": "Tiedot {pageName} ja {productName}", "@knowledge_panel_page_title": { "description": "The title of the page when we click on an item in the product page", "placeholders": { @@ -2810,7 +2899,7 @@ } } }, - "guide_title": "Guide", + "guide_title": "Opas", "@guide_title": { "description": "A title for a guide" }, @@ -2819,7 +2908,7 @@ "@guide_nutriscore_v2_enabled": { "description": "Please NEVER touch this value and let the OFF team change it!" }, - "guide_nutriscore_v2_title": "The Nutri-Score is evolving: explanations!", + "guide_nutriscore_v2_title": "Nutri-Score kehittyy: selityksiä!", "@guide_nutriscore_v2_title": { "description": "The title of the guide (please don't forget the use of non-breaking spaces)" }, @@ -2828,44 +2917,48 @@ "description": "The logo is only available in de/en/fr/ln/nl. Please use en if not available (in lowercase, please)." }, "guide_nutriscore_v2_what_is_nutriscore_title": "Mikä on Nutri-Score?", - "guide_nutriscore_v2_what_is_nutriscore_paragraph1": "The Nutri-Score is a logo which aims to inform you about the **nutritional quality of foods**.", + "guide_nutriscore_v2_what_is_nutriscore_paragraph1": "Nutri-Score on logo, jonka tarkoituksena on kertoa sinulle **ruokien ravintoarvosta**.", "@guide_nutriscore_v2_what_is_nutriscore_paragraph1": { "description": "Text between asterisks (eg: **My Text**) means text in bold. Please try to keep it." }, - "guide_nutriscore_v2_what_is_nutriscore_paragraph2": "The color code varies from dark green (**A**) for the **healthiest** products to dark red (**E**) for the **less healthy** ones.", + "guide_nutriscore_v2_what_is_nutriscore_paragraph2": "Värikoodi vaihtelee tummanvihreästä (**A**) **terveellisimmille** tuotteille tummanpunaiseen (**E**) **vähemmän terveellisille** tuotteille.", "@guide_nutriscore_v2_what_is_nutriscore_paragraph2": { "description": "Text between asterisks (eg: **My Text**) means text in bold. Please try to keep it." }, - "guide_nutriscore_v2_nutriscore_a_caption": "The Nutri-Score A logo", - "guide_nutriscore_v2_why_v2_title": "Why is Nutri-Score evolving?", - "guide_nutriscore_v2_why_v2_intro": "The Nutri-Score formula **is evolving** to provide better recommendations:", - "guide_nutriscore_v2_why_v2_arg1_title": "Better evaluate all drinks", - "guide_nutriscore_v2_why_v2_arg1_text": "The comparative notes of **milk**, **dairy drinks** with added sugar and **vegetable** drinks were better differentiated in the new algorithm.", - "guide_nutriscore_v2_why_v2_arg2_title": "Better ranking of drinks", - "guide_nutriscore_v2_why_v2_arg2_text": "The **sugar content** is better taken into account and favors **lowly sweetened** drinks.\\n**Sweeteners will also be penalized**: diet sodas will be downgraded from a B rating to between C and E. Water remains the recommended drink.", - "guide_nutriscore_v2_why_v2_arg3_title": "Salt and sugar penalized", - "guide_nutriscore_v2_why_v2_arg3_text": "Products **too sweet** or **too salty** will see their **rating further downgraded**.", - "guide_nutriscore_v2_why_v2_arg4_title": "Hierarchy within oils and fishes", - "guide_nutriscore_v2_why_v2_arg4_text": "The rating of certain **fatty fish** and **oils rich in good fats** will improve.", - "guide_nutriscore_v2_why_v2_arg5_title": "Limit red meat", - "guide_nutriscore_v2_why_v2_arg5_text": "Consumption of **red meat should be limited**. This is why **poultry will be comparatively better ranked**.", - "guide_nutriscore_v2_new_logo_title": "How to differentiate old Nutri-Score and new calculation?", - "guide_nutriscore_v2_new_logo_text": "From now on, the logo can display a mention \"**New calculation**\" to clarify that this is indeed the new calculation.", - "guide_nutriscore_v2_new_logo_image_caption": "The logo of the new Nutri-Score", - "guide_nutriscore_v2_where_title": "Where to find the new Nutri-Score calculation?", - "guide_nutriscore_v2_where_paragraph1": "The Nutri-Score is applied in several countries: Germany, Belgium, Spain, France, Luxembourg, the Netherlands and Switzerland.", - "guide_nutriscore_v2_where_paragraph2": "Manufacturers have until **2026** at the latest **to replace** the old calculation with the new one.", - "guide_nutriscore_v2_where_paragraph3": "Without waiting, you **will already find in the OpenFoodFacts application**, the new calculation, including if the manufacturers have not updated the score.", - "guide_nutriscore_v2_unchanged_title": "What doesn't change", - "guide_nutriscore_v2_unchanged_paragraph1": "The Nutri-Score is a score designed to **measure nutritional quality**. It is **complementary to the NOVA group** on **ultra-processed foods** (also present in the application).", - "guide_nutriscore_v2_unchanged_paragraph2": "For manufacturers, the display of the Nutri-Score **remains optional**.", - "guide_nutriscore_v2_share_link": "https://world.openfoodfacts.org/nutriscore-v2", + "guide_nutriscore_v2_nutriscore_a_caption": "Nutri-Score A -logo", + "guide_nutriscore_v2_why_v2_title": "Miksi Nutri-Score kehittyy?", + "guide_nutriscore_v2_why_v2_intro": "Nutri-Score-kaava **kehitetään** tarjotakseen parempia suosituksia:", + "guide_nutriscore_v2_why_v2_arg1_title": "Paranna kaikkien juomien arviointia", + "guide_nutriscore_v2_why_v2_arg1_text": "Uuden algoritmin mukaan **maito**, **sokerilla maustetut maitojuomat** ja **kasvijuomat** eroteltiin paremmin vertailevissa muistiinpanoissa.", + "guide_nutriscore_v2_why_v2_arg2_title": "Parempi juomien sijoitus", + "guide_nutriscore_v2_why_v2_arg2_text": "**Sokeripitoisuus** otetaan paremmin huomioon ja suosii **vähän makeutettuja** juomia.\\n**Makeutusaineista myös rangaistaan**: dieettivirvoitusjuomat alennetaan B-luokituksen tasosta C:n ja E:n välille. Vesi on edelleen suositeltu juoma.", + "guide_nutriscore_v2_why_v2_arg3_title": "Suolasta ja sokerista rangaistaan", + "guide_nutriscore_v2_why_v2_arg3_text": "Tuotteiden, jotka ovat **liian makeita** tai **liian suolaisia**, **luokitusta alennetaan edelleen**.", + "guide_nutriscore_v2_why_v2_arg4_title": "Hierarkia öljyjen ja kalojen välillä", + "guide_nutriscore_v2_why_v2_arg4_text": "Tiettyjen **rasvaisten kalojen** ja **hyviä rasvoja sisältävien öljyjen** luokitus paranee.", + "guide_nutriscore_v2_why_v2_arg5_title": "Rajoita punaista lihaa", + "guide_nutriscore_v2_why_v2_arg5_text": "**Punaisen lihan kulutusta tulisi rajoittaa**. Tämä on syy siihen, miksi **siipikarja sijoittuu suhteellisesti paremmin**.", + "guide_nutriscore_v2_new_logo_title": "Kuinka erottaa vanha Nutri-Score ja uusi laskelma?", + "guide_nutriscore_v2_new_logo_text": "Tästä eteenpäin logossa voi näkyä maininta \"**Uusi laskelma**\" selventääkseen, että kyseessä on todellakin uusi laskelma.", + "guide_nutriscore_v2_new_logo_image_caption": "Uuden Nutri-Scoren logo", + "guide_nutriscore_v2_where_title": "Mistä löydät uuden Nutri-Score-laskelman?", + "guide_nutriscore_v2_where_paragraph1": "Nutri-Scorea sovelletaan useissa maissa: Saksassa, Belgiassa, Espanjassa, Ranskassa, Luxemburgissa, Alankomaissa ja Sveitsissä.", + "guide_nutriscore_v2_where_paragraph2": "Valmistajilla on viimeistään **2026** asti **korvattava** vanha laskelma uudella.", + "guide_nutriscore_v2_where_paragraph3": "Odotamatta **löydät jo OpenFoodFacts-sovelluksesta** uuden laskelman, myös jos valmistajat eivät ole päivittäneet arvosanaa.", + "guide_nutriscore_v2_unchanged_title": "Mikä ei muutu", + "guide_nutriscore_v2_unchanged_paragraph1": "Nutri-Score on pistemäärä, joka on suunniteltu **mittaamaan ravintoarvoa**. Se **täydentää NOVA-ryhmää** **ultrajalostetuissa elintarvikkeissa** (sisältyy myös hakemukseen).", + "guide_nutriscore_v2_unchanged_paragraph2": "Valmistajille Nutri-Score-näyttö **pysyy valinnaisena**.", + "guide_nutriscore_v2_share_link": "https://world-fi.openfoodfacts.org/nutriscore-v2", "guide_nutriscore_v2_share_message": "", "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" }, - "preview_badge": "Preview", + "preview_badge": "Esikatselu", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Napsauta tätä lähettääksesi meille palautetta tästä uudesta ominaisuudesta!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fo.arb b/packages/smooth_app/lib/l10n/app_fo.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_fo.arb +++ b/packages/smooth_app/lib/l10n/app_fo.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_fr.arb b/packages/smooth_app/lib/l10n/app_fr.arb index 4e9ae8dd5b9..fd68a1ba3b5 100644 --- a/packages/smooth_app/lib/l10n/app_fr.arb +++ b/packages/smooth_app/lib/l10n/app_fr.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ok", "@okay": {}, + "validate": "Valider", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Créer", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choisissez des aliments bons pour vous et pour la planète.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Consultez les données alimentaires selon vos préférences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1235,7 +1235,7 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, - "camera_window_accessibility_label": "Scan a barcode with your camera", + "camera_window_accessibility_label": "Scannez un code-barres avec votre appareil photo", "@camera_window_accessibility_label": { "description": "Accessibility label for the camera window" }, @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Pourquoi est-ce que je vois ce message ?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Pour utiliser la fonction \"Extraire les ingrédients\", la photo doit d'abord être téléversée.\n\nVeuillez patienter quelques secondes ou saisissez-les manuellement.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Mettre à jour la photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Pourquoi est-ce que je vois ce message ?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "Pour utiliser la fonction \"Extraire l'emballage\", la photo doit d'abord être téléversée.\n\nVeuillez patienter quelques secondes ou saisissez-les manuellement.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Mettre à jour la photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "URL personnalisée pour les actualités", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL du fichier JSON :", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Non défini", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "État ", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Dernière actualisation: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Raccourci vers l'application Prix sur la page produit", "prices_app_button": "Accéder à l'application Prix", "prices_generic_title": "Prix", @@ -1725,10 +1766,10 @@ "prices_add_a_price": "Ajouter un prix", "prices_add_a_receipt": "Ajouter un ticket de caisse", "prices_add_price_tags": "Ajouter des étiquettes de prix", - "prices_barcode_search_not_found": "Produit non trouvé", + "prices_barcode_search_not_found": "Produit introuvable", "prices_barcode_search_none_yet": "Pas encore de produit", "prices_barcode_search_question": "Voulez-vous chercher ce produit ?", - "prices_barcode_search_title": "Recherche de produit", + "prices_barcode_search_title": "Recherche de produits", "prices_barcode_search_running": "À la recherche de {barcode}", "@prices_barcode_search_running": { "description": "Dialog title about barcode look-up", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Lecteur de code-barres", "prices_view_prices": "Voir les prix", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{Aucun prix} =1{Un seul prix} other{Tous les {count} prix}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{Aucune preuve} =1{Une seule preuve} other{Toutes les {count} preuves}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Configuration du serveur", + "dev_mode_section_news": "Configuration du fournisseur d'actualités", "dev_mode_section_product_page": "Page produit", "dev_mode_section_ui": "Interface utilisateur", "dev_mode_section_data": "Données", @@ -2179,7 +2264,11 @@ }, "capture": "En prendre une autre", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Prendre une photo", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choisir depuis la galerie", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Aperçu", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Cliquez ici pour nous envoyer vos commentaires sur cette nouvelle fonctionnalité !", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ga.arb b/packages/smooth_app/lib/l10n/app_ga.arb index 326ba962b9a..8cac9a8ee7b 100644 --- a/packages/smooth_app/lib/l10n/app_ga.arb +++ b/packages/smooth_app/lib/l10n/app_ga.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tóg pictiúr", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gd.arb b/packages/smooth_app/lib/l10n/app_gd.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_gd.arb +++ b/packages/smooth_app/lib/l10n/app_gd.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gl.arb b/packages/smooth_app/lib/l10n/app_gl.arb index 820ec0df6e8..73cc92d4316 100644 --- a/packages/smooth_app/lib/l10n/app_gl.arb +++ b/packages/smooth_app/lib/l10n/app_gl.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validar", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Datos", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tirar unha foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_gu.arb b/packages/smooth_app/lib/l10n/app_gu.arb index 1ab5d8c7a32..c65f339b13a 100644 --- a/packages/smooth_app/lib/l10n/app_gu.arb +++ b/packages/smooth_app/lib/l10n/app_gu.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "માહિતી", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "ફોટો પાડો", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ha.arb b/packages/smooth_app/lib/l10n/app_ha.arb index 26d87af487c..01aafcb2737 100644 --- a/packages/smooth_app/lib/l10n/app_ha.arb +++ b/packages/smooth_app/lib/l10n/app_ha.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index c4ea97f5154..68b6239d5e8 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "בסדר", "@okay": {}, + "validate": "אימות", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "יצירה", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "בחירה במזון שטוב לך ולכדור הארץ.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "הצגת נתוני המזון שתואמים להעדפות שלך.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -781,7 +781,7 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, - "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "scan_tagline_news_item_accessibility": "חדשות עדכניות: {news_title}", "@scan_tagline_news_item_accessibility": { "description": "Accessibility label for the title of a news", "placeholders": { @@ -1119,8 +1119,8 @@ } } }, - "onboarding_home_welcome_text1": "Welcome !", - "onboarding_home_welcome_text2": "The app that helps you choose food that is good for **you** and the **planet**!", + "onboarding_home_welcome_text1": "ברוך בואך!", + "onboarding_home_welcome_text2": "היישומון שמסייע לך לבחור מזון שטוב **לך** ול**כדור הארץ**!", "@onboarding_home_welcome_text2": { "description": "Onboarding home screen welcome text, text surrounded by * will be bold" }, @@ -1235,7 +1235,7 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, - "camera_window_accessibility_label": "Scan a barcode with your camera", + "camera_window_accessibility_label": "סריקת ברקוד עם המצלמה שלך", "@camera_window_accessibility_label": { "description": "Accessibility label for the camera window" }, @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "למה ההודעה הזאת מופיעה?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "כדי להשתמש ביכולת „חילוץ רכיבים”, קודם יש להעלות את התמונה. \n\nנא להמתין מספר שניות או למלא אותם ידנית.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "רענון תמונה", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "למה ההודעה הזאת מופיעה?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "כדי להשתמש ביכולת „חילוץ אריזה”, קודם יש להעלות את התמונה. \n\nנא להמתין מספר שניות או למלא אותם ידנית.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "רענון תמונה", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,20 +1732,45 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "כתובת מותאמת לחדשות", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "כתובת קובץ JSON:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "לא הוגדרה", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "מצב", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "רענון אחרון: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "קיצור דרך ליישומון מחירים בעמוד המוצר", "prices_app_button": "מעבר ליישומון המחירים", "prices_generic_title": "מחירים", - "prices_add_n_prices": "{count,plural, =1{Add a price} other{App {count} prices}}", - "prices_send_n_prices": "{count,plural, =1{Send the price} other{Send {count} prices}}", - "prices_add_an_item": "Add an item", + "prices_add_n_prices": "{count,plural, one {} two {הוספת {count} מחירים} many {הוספת {count} מחירים}=1{הוספת מחיר{count}} other{הוספת {count} מחירים}}", + "prices_send_n_prices": "{count,plural, one {} two {שליחת {count} מחירים} many {שליחת {count} מחירים}=1{שליחת מחיר {count}} other{שליחת {count} מחירים}}", + "prices_add_an_item": "הוספת פריט", "prices_add_a_price": "הוספת מחיר", - "prices_add_a_receipt": "Add a receipt", - "prices_add_price_tags": "Add price tags", + "prices_add_a_receipt": "הוספת קבלה", + "prices_add_price_tags": "הוספת תגי מחיר", "prices_barcode_search_not_found": "המוצר לא נמצא", - "prices_barcode_search_none_yet": "No product yet", - "prices_barcode_search_question": "Do you want to look for this product?", + "prices_barcode_search_none_yet": "אין מוצרים עדיין", + "prices_barcode_search_question": "לחפש את המוצר הזה?", "prices_barcode_search_title": "חיפוש מוצרים", - "prices_barcode_search_running": "Looking for {barcode}", + "prices_barcode_search_running": "מתבצע איתור אחר {barcode}", "@prices_barcode_search_running": { "description": "Dialog title about barcode look-up", "placeholders": { @@ -1738,9 +1779,21 @@ } } }, - "prices_barcode_reader_action": "Barcode reader", - "prices_view_prices": "View the prices", - "prices_list_length_one_page": "{count,plural, two {כל {count} המחירים} many {כל {count} המחירים}=0{אין מחיר עדיין} =1{מחיר אחד בלבד} other{כל {count} המחירים}}", + "prices_barcode_reader_action": "קורא ברקודים", + "prices_view_prices": "הצגת המחירים", + "prices_product_accessibility_summary": "{count,plural, one {} two {{count} מחירים} many {{count} מחירים}=1{מחיר {count}} other{{count} מחירים}} ל{product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, + "prices_list_length_one_page": "{count,plural, two {כל {count} המחירים} many {כל {count} המחירים}=0{אין מחיר עדיין} =1{מחיר {count} בלבד} other{כל {count} המחירים}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", "placeholders": { @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "מחיר: {price} / חנות: „{location}” / פורסם ב־{date} על ידי „{user}”", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "הוכחות פתוחות של „{user}”", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "הוכחת מחיר פתוח", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1799,7 +1883,7 @@ "prices_amount_price_normal": "מחיר", "prices_amount_price_discounted": "מחיר מוזל", "prices_amount_price_not_discounted": "מחיר מקורי", - "prices_amount_no_product": "One product is missing!", + "prices_amount_no_product": "מוצר אחד חסר!", "prices_amount_price_incorrect": "ערך שגוי", "prices_amount_price_mandatory": "ערך חובה", "prices_currency_subtitle": "מטבע", @@ -1823,20 +1907,21 @@ "@dev_preferences_import_history_result_success": { "description": "User dev preferences - Import history - Result successful" }, - "dev_mode_section_server": "Server configuration", - "dev_mode_section_product_page": "Product page", - "dev_mode_section_ui": "User Interface", + "dev_mode_section_server": "הגדרות שרת", + "dev_mode_section_news": "הגדרות ספק חדשות", + "dev_mode_section_product_page": "עמוד מוצר", + "dev_mode_section_ui": "מנשק משתמש", "dev_mode_section_data": "נתונים", - "dev_mode_section_experimental_features": "Experimental features", + "dev_mode_section_experimental_features": "יכולות ניסיוניות", "dev_mode_hide_ecoscore_title": "להחריג Eco-Score", "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, - "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "dev_mode_spellchecker_for_ocr_title": "להשתמש בבודק איות למסכי סריקה אופטית", "@dev_mode_spellchecker_for_ocr_title": { "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" }, - "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "dev_mode_spellchecker_for_ocr_subtitle": "(רכיבים ואריזה)", "@dev_mode_spellchecker_for_ocr_subtitle": { "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" }, @@ -2096,7 +2181,7 @@ "@product_list_select": { "description": "Top title for the selection of a list" }, - "user_list_length": "{count,plural, two {שני מוצרים} many {{count} מוצרים} =0{רשימה ריקה} =1{מוצר אחד} other{{count} מוצרים}}", + "user_list_length": "{count,plural, two {{count} מוצרים} many {{count} מוצרים} =0{רשימה ריקה} =1{מוצר {count}} other{{count} מוצרים}}", "@user_list_length": { "description": "Length of a user product list", "placeholders": { @@ -2179,7 +2264,11 @@ }, "capture": "לצלם חדשה", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "צילום תמונה", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "בחירה מהגלריה", "@choose_from_gallery": { @@ -2387,7 +2476,7 @@ "@robotoff_continue": { "description": "Shown when robotoff question are all answered and user wants to continue answering" }, - "robotoff_next_n_questions": "{count,plural, two {{count} השאלות הבאות} many {{count} השאלות הבאות}=1{השאלה הבאה} other{{count} השאלות הבאות}}", + "robotoff_next_n_questions": "{count,plural, two {{count} השאלות הבאות} many {{count} השאלות הבאות}=1{שאלה {count} הבאה} other{{count} השאלות הבאות}}", "@robotoff_next_n_questions": { "description": "Shown when robotoff question are all answered and user wants to continue answering", "placeholders": { @@ -2771,7 +2860,7 @@ "faq_title_install_beauty": "אפשר להתקין את Open Beauty Facts כדי ליצור מסד נתונים קוסמטי", "faq_title_install_pet": "אפשר להתקין את Open Pet Food Facts כדי ליצור מסד נתוני מזון לחיות מחמד", "faq_title_install_product": "אפשר להתקין את Open Products Facts כדי ליצור מסד נתונים של מוצרים להארכת חיי הפריטים", - "faq_nutriscore_nutriscore": "New calculation of the Nutri-Score: what's new?", + "faq_nutriscore_nutriscore": "נוסחה חדשה ל־Nutri-Score: מה השתנה?", "contact_title_pro_page": "יצרנים? אפשר לייבא את המוצרים שלכם ל־Open Food Facts", "contact_title_pro_email": "איש קשר ליצרנים", "contact_title_press_page": "עמוד לעיתונאים", @@ -2864,8 +2953,12 @@ "@guide_nutriscore_v2_share_message": { "description": "Please let empty for now (maybe use in the future)" }, - "preview_badge": "Preview", + "preview_badge": "תצוגה מקדימה", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "נא ללחוץ כאן כדי לשלוח לנו משוב על היכולת החדשה הזאת!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hi.arb b/packages/smooth_app/lib/l10n/app_hi.arb index a1f35fb3f93..401690871ab 100644 --- a/packages/smooth_app/lib/l10n/app_hi.arb +++ b/packages/smooth_app/lib/l10n/app_hi.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "जानकारी", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "एक तस्वीर ले लो", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hr.arb b/packages/smooth_app/lib/l10n/app_hr.arb index 0c4bb37ef9e..6be887be2b1 100644 --- a/packages/smooth_app/lib/l10n/app_hr.arb +++ b/packages/smooth_app/lib/l10n/app_hr.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Dobro", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Podaci", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Uslikaj", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ht.arb b/packages/smooth_app/lib/l10n/app_ht.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_ht.arb +++ b/packages/smooth_app/lib/l10n/app_ht.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hu.arb b/packages/smooth_app/lib/l10n/app_hu.arb index 9854b5b93cb..89b00fb9051 100644 --- a/packages/smooth_app/lib/l10n/app_hu.arb +++ b/packages/smooth_app/lib/l10n/app_hu.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Rendben", "@okay": {}, + "validate": "Érvényesítés", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Létrehoz", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Válassz olyan ételt, amely jó neked és a bolygónak.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Tekintse meg az Ön preferenciáinak megfelelő élelmiszeradatokat.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Állapot", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Adatok", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Készítsen képet", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_hy.arb b/packages/smooth_app/lib/l10n/app_hy.arb index d7770356fdc..9efc26f25eb 100644 --- a/packages/smooth_app/lib/l10n/app_hy.arb +++ b/packages/smooth_app/lib/l10n/app_hy.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_id.arb b/packages/smooth_app/lib/l10n/app_id.arb index 96d58d02f4d..e31b84f64aa 100644 --- a/packages/smooth_app/lib/l10n/app_id.arb +++ b/packages/smooth_app/lib/l10n/app_id.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Baik", "@okay": {}, + "validate": "Validasikan", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Buat", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Pilih makanan yang baik untuk Anda dan untuk planet ini.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Lihat data makanan yang cocok dengan preferensi Anda.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Muat ulang foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Muat ulang foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Pintasan ke aplikasi Harga di halaman produk", "prices_app_button": "Buka aplikasi Harga", "prices_generic_title": "Harga", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "Lihat harga", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{Belum ada harga} =1{Hanya satu harga} other{Semua {count} harga}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Foto Baru", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ambil gambar", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Pilih dari galeri", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ii.arb b/packages/smooth_app/lib/l10n/app_ii.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_ii.arb +++ b/packages/smooth_app/lib/l10n/app_ii.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_is.arb b/packages/smooth_app/lib/l10n/app_is.arb index 9fe368ece44..79690d031e7 100644 --- a/packages/smooth_app/lib/l10n/app_is.arb +++ b/packages/smooth_app/lib/l10n/app_is.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_it.arb b/packages/smooth_app/lib/l10n/app_it.arb index 2492bb195b3..3f90393f1af 100644 --- a/packages/smooth_app/lib/l10n/app_it.arb +++ b/packages/smooth_app/lib/l10n/app_it.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ok", "@okay": {}, + "validate": "Convalida", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Crea", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Scegli gli alimenti che fanno bene a te e al pianeta.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Visualizza i dati alimentari rilevanti alle tue preferenze.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -244,7 +244,7 @@ }, "sign_up_page_password_hint": "Password", "sign_up_page_password_error_empty": "Inserire una password", - "sign_up_page_password_error_invalid": "Sei pregato di inserire una password valida (almeno 6 caratteri)", + "sign_up_page_password_error_invalid": "Per favore inserisci una password valida (almeno 6 caratteri)", "sign_up_page_confirm_password_hint": "Ripeti la password", "sign_up_page_confirm_password_error_empty": "Ripeti la password", "sign_up_page_confirm_password_error_invalid": "Le password non corrispondono", @@ -270,7 +270,7 @@ }, "sign_up_page_producer_checkbox": "Sono un produttore di alimenti", "sign_up_page_producer_hint": "Produttore/marca", - "sign_up_page_producer_error_empty": "Sei pregato di inserire il nome di un produttore o marchio", + "sign_up_page_producer_error_empty": "Per favore inserisci il nome di un produttore o di una marca", "sign_up_page_subscribe_checkbox": "Vorrei iscrivermi alla newsletter di Open Food facts (Puoi disiscriverti in qualsiasi momento)", "sign_up_page_user_name_already_used": "Il nome utente esiste già, ti preghiamo di sceglierne un altro.", "sign_up_page_email_already_exists": "esiste già, accedi al profilo o prova con un'altra email.", @@ -398,7 +398,7 @@ "@tap_to_answer_hint": { "description": "Hint for accessibility readers to answer Robotoff questions." }, - "robotoff_questions_loading_hint": "Sei pregato di attendere durante il caricamento delle domande su questo prodotto", + "robotoff_questions_loading_hint": "Per favore attendi durante il caricamento delle domande su questo prodotto", "@robotoff_questions_loading_hint": { "description": "Hint for accessibility readers while Robotoff questions are loaded" }, @@ -781,7 +781,7 @@ "@homepage_main_card_search_field_tooltip": { "description": "Description for accessibility of the search field on the homepage" }, - "scan_tagline_news_item_accessibility": "Latest news: {news_title}", + "scan_tagline_news_item_accessibility": "Ultime notizie: {news_title}", "@scan_tagline_news_item_accessibility": { "description": "Accessibility label for the title of a news", "placeholders": { @@ -837,19 +837,19 @@ "@product_improvement_add_nutrition_facts_and_category": { "description": "Message for ProductImprovement.ADD_NUTRITION_FACTS_AND_CATEGORY" }, - "product_improvement_categories_but_no_nutriscore": "Il Nutri-Score per questo prodotto non è calcolabile, il che potrebbe dipendere da, es. una categoria non standard. Se ciò è considerato un errore, sei pregato di contattarci.", + "product_improvement_categories_but_no_nutriscore": "Il Nutri-Score per questo prodotto non può essere calcolato, il che potrebbe dipendere da ad es. una categoria non standard. Se consideri questo un errore, per favore contattaci.", "@product_improvement_categories_but_no_nutriscore": { "description": "Message for ProductImprovement.CATEGORIES_BUT_NO_NUTRISCORE" }, - "product_improvement_obsolete_nutrition_image": "L'immagine nutrizionale è obsoleta: sei pregato di aggiornarla.", + "product_improvement_obsolete_nutrition_image": "L'immagine nutrizionale è obsoleta: per favore aggiornala.", "@product_improvement_obsolete_nutrition_image": { "description": "Message for ProductImprovement.OBSOLETE_NUTRITION_IMAGE" }, - "product_improvement_origins_to_be_completed": "L'Eco-Score tiene in considerazione le origini degli ingredienti. Sei pregato di scattare una foto della lista di ingredienti e/o ogni rivendicazione geografica o modifica il prodotto, così che possa esser preso in considerazione.", + "product_improvement_origins_to_be_completed": "L'Eco-Score tiene in considerazione le origini degli ingredienti. Se puoi scatta una foto della lista degli ingredienti e/o di qualsiasi dichiarazione geografica o modifica il prodotto, in modo che possano essere presi in considerazione.", "@product_improvement_origins_to_be_completed": { "description": "Message for ProductImprovement.ORIGINS_TO_BE_COMPLETED" }, - "country_chooser_label": "Sei pregato di scegliere un paese", + "country_chooser_label": "Scegli un Paese", "@country_chooser_label": { "description": "Label shown above a selector where the user can select their country (in the preferences)" }, @@ -891,7 +891,7 @@ "@product_removed_comparison": { "description": "Product got removed from comparison list" }, - "native_app_settings": "Impostazioni dell'App Nativa", + "native_app_settings": "Impostazioni native dell'App", "@native_app_settings": { "description": "Native App Settings in app settings" }, @@ -1183,7 +1183,7 @@ "@user_profile": { "description": "User account (if connected)" }, - "user_profile_title_guest": "Benvenuto!", + "user_profile_title_guest": "Benvenuto/a!", "@user_profile_title_guest": { "description": "When the user is not connected" }, @@ -1235,11 +1235,11 @@ "@camera_play_sound_subtitle": { "description": "SubTitle for the Camera play sound toggle" }, - "camera_window_accessibility_label": "Scan a barcode with your camera", + "camera_window_accessibility_label": "Scansiona un codice a barre con la tua fotocamera", "@camera_window_accessibility_label": { "description": "Accessibility label for the camera window" }, - "app_haptic_feedback_title": "Vibrazione e Tatto", + "app_haptic_feedback_title": "Vibrazione e sensazioni tattili", "@app_haptic_feedback_title": { "description": "Title for the Haptic feedback toggle" }, @@ -1247,11 +1247,11 @@ "@app_haptic_feedback_subtitle": { "description": "SubTitle for the Haptic feedback toggle" }, - "crash_reporting_toggle_title": "Segnala crash", + "crash_reporting_toggle_title": "Segnalazione di arresti anomali", "@crash_reporting_toggle_title": { "description": "Title for the Crash reporting toggle" }, - "crash_reporting_toggle_subtitle": "Quando abilitati, i rapporti sugli arresti anomali sono inviati automaticamente al sistema di monitoraggio degli errori di Open Food Facts, così che i bug possano essere risolti e, dunque, che l'app possa essere migliorata.", + "crash_reporting_toggle_subtitle": "Quando abilitato, i rapporti sugli arresti anomali vengono inviati automaticamente al sistema di monitoraggio degli errori di Open Food Facts, così che i bug possano essere risolti e dunque che l'app possa essere migliorata.", "@crash_reporting_toggle_subtitle": { "description": "SubTitle for the Crash reporting toggle" }, @@ -1259,7 +1259,7 @@ "@send_anonymous_toggle_title": { "description": "Title for the Send anonymous data toggle" }, - "send_anonymous_data_toggle_subtitle": "Quando abilitate, alcune informazioni anonime relative all'utilizzo dell'app saranno inviate ai server di Open Food Facts, quindi, potremo comprendere come e quante funzionalità sono utilizzate, così da migliorarle.", + "send_anonymous_data_toggle_subtitle": "Quando abilitato, alcune informazioni anonime relative all'utilizzo dell'app saranno inviate ai server di Open Food Facts, in modo che possiamo comprendere come e quante funzionalità vengono utilizzate, così da migliorarle.", "@send_anonymous_toggle_subtitle": { "description": "SubTitle for the Send anonymous data toggle" }, @@ -1272,7 +1272,7 @@ "description": "When the camera/photo permission failed to be acquired (!= denied)" }, "permission_photo_denied_title": "Consenti l'uso della fotocamera per scansionare i codici a barre", - "permission_photo_denied_message": "Per un'esperienza migliore, sei pregato di consentire a {appName} di accedere alla tua fotocamera. Potrai scansionare direttamente i codici a barre.", + "permission_photo_denied_message": "Per un'esperienza migliore, consenti a {appName} di accedere alla tua fotocamera. Potrai scansionare direttamente i codici a barre.", "@permission_photo_denied_message": { "description": "When the camera/photo permission is denied by user", "placeholders": { @@ -1450,7 +1450,7 @@ "description": "Product edition - Ingredients - Title (note: this section was previously called Ingredients & Origins)" }, "edit_product_form_item_add_valid_item_tooltip": "Aggiungi", - "edit_product_form_item_add_invalid_item_tooltip": "Sei pregato di inserire prima un testo", + "edit_product_form_item_add_invalid_item_tooltip": "Per favore inserisci prima un testo", "edit_product_form_item_remove_item_tooltip": "Rimuovi", "edit_product_form_item_packaging_title": "Foto delle istruzioni di riciclaggio", "@edit_product_form_item_packaging_title": { @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Perché vedo questo messaggio?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Per utilizzare la funzionalità \"Estrai ingredienti\", è necessario prima caricare la foto.\n\nAttendi qualche secondo o inseriscili manualmente.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Aggiorna foto", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Perché vedo questo messaggio?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Aggiorna foto", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1535,7 +1551,7 @@ "@user_list_button_new": { "description": "Short label of a 'create a new list' button" }, - "user_list_empty_label": "Ancora nessuna lista disponibile, ti preghiamo di iniziare a crearne una", + "user_list_empty_label": "Nessuna lista ancora disponibile, inizia creandone una", "@user_list_empty_label": { "description": "Content displayed when there is no list" }, @@ -1716,10 +1732,35 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "URL personalizzato per le notizie", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL del file JSON:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Non specificato", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Stato", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Ultimo aggiornamento: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Collegamento all'app Prezzi sulla pagina del prodotto", "prices_app_button": "Vai all'app Prezzi", "prices_generic_title": "Prezzi", - "prices_add_n_prices": "{count,plural, one {}=1{Aggiungi un prezzo} other{Aggiungi {count} prezzi}}", + "prices_add_n_prices": "{count,plural, =1{Aggiungi un prezzo} other{Aggiungi {count} prezzi}}", "prices_send_n_prices": "{count,plural, =1{Invia il prezzo} other{Invia {count} prezzi}}", "prices_add_an_item": "Aggiungi un elemento", "prices_add_a_price": "Aggiungi un prezzo", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Lettore del codice a barre", "prices_view_prices": "Guarda i prezzi", + "prices_product_accessibility_summary": "{count,plural, =1{1 prezzo} other{{count} prezzi}} per {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{Ancora nessun prezzo} =1{Solo un prezzo} other{Tutti e {count} i prezzi}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Prezzo: {price} / Negozio: \"{location}\" / Pubblicato il {date} da \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Apri le prove di \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Apri la prova del prezzo", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{Ancora nessuna prova} =1{Solo una prova} other{Tutte e {count} le prove}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Configurazione del server", + "dev_mode_section_news": "Configurazione del fornitore di notizie", "dev_mode_section_product_page": "Pagina del prodotto", "dev_mode_section_ui": "Interfaccia utente", "dev_mode_section_data": "Dati", @@ -1832,11 +1917,11 @@ "@dev_mode_hide_ecoscore_title": { "description": "User dev preferences - Disable Ecoscore - Title" }, - "dev_mode_spellchecker_for_ocr_title": "Use a spellchecker for OCR screens", + "dev_mode_spellchecker_for_ocr_title": "Usa un correttore ortografico per le schermate OCR", "@dev_mode_spellchecker_for_ocr_title": { "description": "User dev preferences - Enable Spellchecker on OCR screens - Title" }, - "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredients and packaging)", + "dev_mode_spellchecker_for_ocr_subtitle": "(Ingredienti e confezione)", "@dev_mode_spellchecker_for_ocr_subtitle": { "description": "User dev preferences - Enable Spellchecker on OCR screens - Subtitle" }, @@ -2017,7 +2102,7 @@ "product_name": "Nome del prodotto", "add_basic_details_product_name_error": "Si prega di inserire il nome del prodotto", "brand_name": "Nome del marchio", - "add_basic_details_brand_name_error": "Sei pregato di inserire il nome del marchio", + "add_basic_details_brand_name_error": "Si prega d'inserire il nome della marca", "quantity": "Quantità e peso", "barcode": "Codice a Barre", "barcode_barcode": "Codice a barre: {barcode}", @@ -2177,9 +2262,13 @@ } } }, - "capture": "Cattura Nuovo", + "capture": "Scatta una nuova foto", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Scatta una foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Scegli dalla galleria", "@choose_from_gallery": { @@ -2503,7 +2592,7 @@ "@copy_email_to_clip_board": { "description": "Button: Copy the email adress to the clipboard. Shown when an automatic opening of an email application is not possible" }, - "please_send_us_an_email_to": "Sei pregato di inviarci manualmente un'email a", + "please_send_us_an_email_to": "Per favore inviaci manualmente un'e-mail a", "email_copied_to_clip_board": "Email copiata negli appunti!", "select_accent_color": "Seleziona il Colore Secondario", "@select_accent_color": { @@ -2612,7 +2701,7 @@ "@product_loader_network_error_title": { "description": "When fetching a product opened via a link and there is no connection" }, - "product_loader_network_error_message": "Sei pregato di verificare che il tuo smartphone sia connesso a una rete WiFi o ai dati mobili", + "product_loader_network_error_message": "Sei pregato di verificare che il tuo smartphone sia connesso a una rete WiFi o abbia i dati mobili abilitati", "@product_loader_network_error_message": { "description": "When fetching a product opened via a link and there is no connection" }, @@ -2867,5 +2956,9 @@ "preview_badge": "Anteprima", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Clicca qui per inviarci il tuo feedback su questa nuova funzionalità!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_iu.arb b/packages/smooth_app/lib/l10n/app_iu.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_iu.arb +++ b/packages/smooth_app/lib/l10n/app_iu.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ja.arb b/packages/smooth_app/lib/l10n/app_ja.arb index 1bfa02af466..47460e0c8ff 100644 --- a/packages/smooth_app/lib/l10n/app_ja.arb +++ b/packages/smooth_app/lib/l10n/app_ja.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "OK", "@okay": {}, + "validate": "検証", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "あなたと地球にとって良い食品を選んでください。", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "あなたの好みに関連する食品データを確認する。", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "画像を更新", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "画像を更新", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "状態", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "製品ページの価格アプリへのショートカット", "prices_app_button": "価格アプリに移動", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "サーバー設定", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "製品ページ", "dev_mode_section_ui": "ユーザインタフェース", "dev_mode_section_data": "データ", @@ -2179,7 +2264,11 @@ }, "capture": "新しく撮影する", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "画像を撮る", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "ギャラリーから選択する", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "プレビュー", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_jv.arb b/packages/smooth_app/lib/l10n/app_jv.arb index 6c4b65f2656..cd76fccf6aa 100644 --- a/packages/smooth_app/lib/l10n/app_jv.arb +++ b/packages/smooth_app/lib/l10n/app_jv.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ka.arb b/packages/smooth_app/lib/l10n/app_ka.arb index f1dc68c9413..2da0c0c6b80 100644 --- a/packages/smooth_app/lib/l10n/app_ka.arb +++ b/packages/smooth_app/lib/l10n/app_ka.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "კარგი", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "მონაცემები", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kk.arb b/packages/smooth_app/lib/l10n/app_kk.arb index 31602b9438c..97986d486ab 100644 --- a/packages/smooth_app/lib/l10n/app_kk.arb +++ b/packages/smooth_app/lib/l10n/app_kk.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Деректер", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Суретке түсіру", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_km.arb b/packages/smooth_app/lib/l10n/app_km.arb index 781be4d126e..2b7822ca846 100644 --- a/packages/smooth_app/lib/l10n/app_km.arb +++ b/packages/smooth_app/lib/l10n/app_km.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "យល់ព្រម", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kn.arb b/packages/smooth_app/lib/l10n/app_kn.arb index e6acc91c335..9b5d5b7941a 100644 --- a/packages/smooth_app/lib/l10n/app_kn.arb +++ b/packages/smooth_app/lib/l10n/app_kn.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ko.arb b/packages/smooth_app/lib/l10n/app_ko.arb index c0f68d34417..f8b20aa50e5 100644 --- a/packages/smooth_app/lib/l10n/app_ko.arb +++ b/packages/smooth_app/lib/l10n/app_ko.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "확인", "@okay": {}, + "validate": "검사", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "만들기", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "당신과 지구에 좋은 음식을 고르세요.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "당신의 선호도와 관련된 식품 데이터를 확인하세요.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "사진 새로고침", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "사진 새로고침", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "상태", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "데이터", @@ -2179,7 +2264,11 @@ }, "capture": "새 캡처", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "사진을 촬영", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "갤러리에서 선택", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ku.arb b/packages/smooth_app/lib/l10n/app_ku.arb index 22cdd3a1ecb..4b1f7436100 100644 --- a/packages/smooth_app/lib/l10n/app_ku.arb +++ b/packages/smooth_app/lib/l10n/app_ku.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Dane", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Bigire a resma", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_kw.arb b/packages/smooth_app/lib/l10n/app_kw.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_kw.arb +++ b/packages/smooth_app/lib/l10n/app_kw.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ky.arb b/packages/smooth_app/lib/l10n/app_ky.arb index e25dd64a1fc..1bdbce26605 100644 --- a/packages/smooth_app/lib/l10n/app_ky.arb +++ b/packages/smooth_app/lib/l10n/app_ky.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Түзүү", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_la.arb b/packages/smooth_app/lib/l10n/app_la.arb index 46f1db800b4..1c3f8a6246a 100644 --- a/packages/smooth_app/lib/l10n/app_la.arb +++ b/packages/smooth_app/lib/l10n/app_la.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lb.arb b/packages/smooth_app/lib/l10n/app_lb.arb index ccb380f1be2..4ef44f858f3 100644 --- a/packages/smooth_app/lib/l10n/app_lb.arb +++ b/packages/smooth_app/lib/l10n/app_lb.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validéieren", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Daten", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Eng Foto maachen", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lo.arb b/packages/smooth_app/lib/l10n/app_lo.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_lo.arb +++ b/packages/smooth_app/lib/l10n/app_lo.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lt.arb b/packages/smooth_app/lib/l10n/app_lt.arb index bb1e3be0bcf..e740149012d 100644 --- a/packages/smooth_app/lib/l10n/app_lt.arb +++ b/packages/smooth_app/lib/l10n/app_lt.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Gerai", "@okay": {}, + "validate": "Patvirtinti", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Kurti", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Pasirinkite maistą, kuris tinka jums ir planetai.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Peržiūrėkite maisto duomenis, atitinkančius jūsų pageidavimus.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Kodėl matau šį pranešimą?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Kad pasinaudotumėte funkcija „Ištraukti sudedamąsias dalis“, pirmiausia reikia įkelti nuotrauką.\n\nPalaukite kelias sekundes arba įveskite rankiniu būdu.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Atnaujinti nuotrauką", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Kodėl matau šį pranešimą?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "Kad pasinaudotumėte funkcija „Ištraukti pakuotę“, pirmiausia reikia įkelti nuotrauką.\n\nPalaukite kelias sekundes arba įveskite rankiniu būdu.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Atnaujinti nuotrauką", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Pasirinktinis naujienų URL", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "JSON failo URL:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Nenustatytas", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Būsena", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Paskutinis atnaujinimas: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Kainos", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Kaina: {price} / parduotuvė: \"{location}\" / Paskėlbė {date} \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Atverti \"{user}\" įrodymus", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Atverti kainos įrodymą", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "Naujienų teikėjo konfigūravimas", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Duomenys", @@ -2177,9 +2262,13 @@ } } }, - "capture": "Užfiksuoti naują", + "capture": "Nufotografuoti naują nuotrauką", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Fotografuoti", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Pasirinkti iš galerijos", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_lv.arb b/packages/smooth_app/lib/l10n/app_lv.arb index 4ad54b5bc97..6803f33da64 100644 --- a/packages/smooth_app/lib/l10n/app_lv.arb +++ b/packages/smooth_app/lib/l10n/app_lv.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Izveidot", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Dati", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Fotografēt", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mg.arb b/packages/smooth_app/lib/l10n/app_mg.arb index 1b02b9c351c..879a5b24cb7 100644 --- a/packages/smooth_app/lib/l10n/app_mg.arb +++ b/packages/smooth_app/lib/l10n/app_mg.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Firaketana", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Makà sary", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mi.arb b/packages/smooth_app/lib/l10n/app_mi.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_mi.arb +++ b/packages/smooth_app/lib/l10n/app_mi.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ml.arb b/packages/smooth_app/lib/l10n/app_ml.arb index 32ed0e37b08..c523bcb7b65 100644 --- a/packages/smooth_app/lib/l10n/app_ml.arb +++ b/packages/smooth_app/lib/l10n/app_ml.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mn.arb b/packages/smooth_app/lib/l10n/app_mn.arb index 8a115b77caa..b703ef87451 100644 --- a/packages/smooth_app/lib/l10n/app_mn.arb +++ b/packages/smooth_app/lib/l10n/app_mn.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Баталгаажуулах", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mr.arb b/packages/smooth_app/lib/l10n/app_mr.arb index 271cbc1b4d9..9071ad5a1e3 100644 --- a/packages/smooth_app/lib/l10n/app_mr.arb +++ b/packages/smooth_app/lib/l10n/app_mr.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Thik aahe", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ms.arb b/packages/smooth_app/lib/l10n/app_ms.arb index 1f0388e91eb..f4f493617c0 100644 --- a/packages/smooth_app/lib/l10n/app_ms.arb +++ b/packages/smooth_app/lib/l10n/app_ms.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okey", "@okay": {}, + "validate": "Tentusahkan", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Lihat data makanan yang berkaitan dengan pilihan anda.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ambil gambar", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_mt.arb b/packages/smooth_app/lib/l10n/app_mt.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_mt.arb +++ b/packages/smooth_app/lib/l10n/app_mt.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_my.arb b/packages/smooth_app/lib/l10n/app_my.arb index 3f4d81b5caf..02c3f2c43be 100644 --- a/packages/smooth_app/lib/l10n/app_my.arb +++ b/packages/smooth_app/lib/l10n/app_my.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nb.arb b/packages/smooth_app/lib/l10n/app_nb.arb index 5832be15d1a..21ea0f04da2 100644 --- a/packages/smooth_app/lib/l10n/app_nb.arb +++ b/packages/smooth_app/lib/l10n/app_nb.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ok", "@okay": {}, + "validate": "Godkjenn", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Opprett", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Velg mat som er bra for deg og planeten.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Se matdata som er relevant for dine preferanser.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Oppdater bildet", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Oppdater bildet", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ta et bilde", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Velg fra bildegalleri", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ne.arb b/packages/smooth_app/lib/l10n/app_ne.arb index 265c5e357ac..05fc89a31ec 100644 --- a/packages/smooth_app/lib/l10n/app_ne.arb +++ b/packages/smooth_app/lib/l10n/app_ne.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "ल", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nl.arb b/packages/smooth_app/lib/l10n/app_nl.arb index 478c8712e5c..d444cb76771 100644 --- a/packages/smooth_app/lib/l10n/app_nl.arb +++ b/packages/smooth_app/lib/l10n/app_nl.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Oké", "@okay": {}, + "validate": "Bevestigen", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Aanmaken", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Kies voedsel dat goed is voor jou en de planeet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Bekijk de voedselgegevens die relevant zijn voor uw voorkeuren.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Waarom zie ik dit bericht?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Om de functie 'Ingrediënten extraheren' te gebruiken, moet de foto eerst worden geüpload.\n\nWacht een paar seconden of voer de ingrediënten handmatig in.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Foto vernieuwen", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Waarom zie ik dit bericht?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "Om de functie \"Verpakkingsgegevens extraheren\" te gebruiken, moet de foto eerst worden geüpload.\n\nWacht alstublieft een paar seconden of voer de verpakkingsgegevens handmatig in.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Foto vernieuwen", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Aangepaste URL voor nieuws", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL van het JSON-bestand:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Niet ingesteld", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Toestand", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Laatste vernieuwing: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Snelkoppeling naar de Prijzen-app op de productpagina", "prices_app_button": "Ga naar de Prijzen-app", "prices_generic_title": "Prijzen", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Streepjescodelezer", "prices_view_prices": "Bekijk de prijzen", + "prices_product_accessibility_summary": "{count,plural, one {}=1{1 prijs} other{{count} prijzen}} voor {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, one {}=0{Nog geen prijs} =1{Slechts één prijs} other{Alle {count} prijzen}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Prijs: {price} / Winkel: \"{location}\" / Gepubliceerd op {date} door \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Bewijzen openen van \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Prijsbewijs openen", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, one {}=0{Nog geen bewijs} =1{Slechts één bewijs} other{Alle {count} bewijzen}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Serverconfiguratie", + "dev_mode_section_news": "Configuratie van nieuwsprovider", "dev_mode_section_product_page": "Productpagina", "dev_mode_section_ui": "Gebruikersinterface", "dev_mode_section_data": "Gegevens", @@ -2177,9 +2262,13 @@ } } }, - "capture": "Nieuwe vastleggen", + "capture": "Maak een nieuwe foto", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Maak een foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Kies uit gallerij", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Voorbeeld", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Klik hier om ons uw feedback over deze nieuwe functie te sturen!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nn.arb b/packages/smooth_app/lib/l10n/app_nn.arb index 1731558508f..08ef016ebdb 100644 --- a/packages/smooth_app/lib/l10n/app_nn.arb +++ b/packages/smooth_app/lib/l10n/app_nn.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ta et bilde", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_no.arb b/packages/smooth_app/lib/l10n/app_no.arb index 1731558508f..08ef016ebdb 100644 --- a/packages/smooth_app/lib/l10n/app_no.arb +++ b/packages/smooth_app/lib/l10n/app_no.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ta et bilde", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_nr.arb b/packages/smooth_app/lib/l10n/app_nr.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_nr.arb +++ b/packages/smooth_app/lib/l10n/app_nr.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_oc.arb b/packages/smooth_app/lib/l10n/app_oc.arb index efd39816bd6..68e74253e48 100644 --- a/packages/smooth_app/lib/l10n/app_oc.arb +++ b/packages/smooth_app/lib/l10n/app_oc.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Crear", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Donadas", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_or.arb b/packages/smooth_app/lib/l10n/app_or.arb index b10968f9050..60645b22e1f 100644 --- a/packages/smooth_app/lib/l10n/app_or.arb +++ b/packages/smooth_app/lib/l10n/app_or.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "ଠିକ୍ ଅଛି", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pa.arb b/packages/smooth_app/lib/l10n/app_pa.arb index a3502859bad..bd1ad1f4d30 100644 --- a/packages/smooth_app/lib/l10n/app_pa.arb +++ b/packages/smooth_app/lib/l10n/app_pa.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pl.arb b/packages/smooth_app/lib/l10n/app_pl.arb index 47b3825a9ed..9d2cf82bac5 100644 --- a/packages/smooth_app/lib/l10n/app_pl.arb +++ b/packages/smooth_app/lib/l10n/app_pl.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "OK", "@okay": {}, + "validate": "Zweryfikuj", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Stwórz", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Wybierz produkty, które są dobre dla Ciebie i naszej planety.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Zobacz dane dotyczące żywności odpowiadające Twoim preferencjom.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Odśwież zdjęcie", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Odśwież zdjęcie", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Ceny", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Dane", @@ -2179,7 +2264,11 @@ }, "capture": "Zrób zdjęcie", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Zrób zdjęcie", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Wybierz z galerii", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_pt.arb b/packages/smooth_app/lib/l10n/app_pt.arb index 14dccb75a57..6a32c08ebac 100644 --- a/packages/smooth_app/lib/l10n/app_pt.arb +++ b/packages/smooth_app/lib/l10n/app_pt.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ok", "@okay": {}, + "validate": "Validar", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Criar", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Escolha alimentos que são bons para você e para o planeta.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Veja as informações nutricionais relevantes às suas preferências.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Atualizar fotografia", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Atualizar fotografia", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Estado", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Atalho para a aplicação Preços na página do produto", "prices_app_button": "Ir para a aplicação Preços", "prices_generic_title": "Preços", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "Ver os preços", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{Ainda sem preço} =1{Apenas um preço} other{Todos os {count} preços}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Dados", @@ -2179,7 +2264,11 @@ }, "capture": "Fotografar mais recente", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Tirar uma foto", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Escolher da galeria", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_qu.arb b/packages/smooth_app/lib/l10n/app_qu.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_qu.arb +++ b/packages/smooth_app/lib/l10n/app_qu.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_rm.arb b/packages/smooth_app/lib/l10n/app_rm.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_rm.arb +++ b/packages/smooth_app/lib/l10n/app_rm.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ro.arb b/packages/smooth_app/lib/l10n/app_ro.arb index c911d649da4..2f30a2df89b 100644 --- a/packages/smooth_app/lib/l10n/app_ro.arb +++ b/packages/smooth_app/lib/l10n/app_ro.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Bine", "@okay": {}, + "validate": "Validați", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Crează", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Alege alimente care sunt bune pentru tine și planetă.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Vedeți datele despre alimente relevante pentru preferințele dvs.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Reîmprospătați fotografia", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Reîmprospătați fotografia", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Stare", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Date", @@ -2179,7 +2264,11 @@ }, "capture": "Captură nouă", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Faceți o fotografie", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Alegeți din galerie", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ru.arb b/packages/smooth_app/lib/l10n/app_ru.arb index 71a326333cc..7c37e7f1a3a 100644 --- a/packages/smooth_app/lib/l10n/app_ru.arb +++ b/packages/smooth_app/lib/l10n/app_ru.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Окей", "@okay": {}, + "validate": "Подтвердить", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Создать", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Выбирайте еду, которая полезна для вас и для планеты.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Смотрите данные о еде, соответствующие вашим предпочтениям.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Обновить фото", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Обновить фото", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Статус", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Данные", @@ -2179,7 +2264,11 @@ }, "capture": "Новый снимок", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Сфотографировать", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Выбрать из галереи", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sa.arb b/packages/smooth_app/lib/l10n/app_sa.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_sa.arb +++ b/packages/smooth_app/lib/l10n/app_sa.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sc.arb b/packages/smooth_app/lib/l10n/app_sc.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_sc.arb +++ b/packages/smooth_app/lib/l10n/app_sc.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sd.arb b/packages/smooth_app/lib/l10n/app_sd.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_sd.arb +++ b/packages/smooth_app/lib/l10n/app_sd.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sg.arb b/packages/smooth_app/lib/l10n/app_sg.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_sg.arb +++ b/packages/smooth_app/lib/l10n/app_sg.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_si.arb b/packages/smooth_app/lib/l10n/app_si.arb index e211d286d36..48abd7d0846 100644 --- a/packages/smooth_app/lib/l10n/app_si.arb +++ b/packages/smooth_app/lib/l10n/app_si.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sk.arb b/packages/smooth_app/lib/l10n/app_sk.arb index 68e27d8b0d5..be92b8d34de 100644 --- a/packages/smooth_app/lib/l10n/app_sk.arb +++ b/packages/smooth_app/lib/l10n/app_sk.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "V poriadku", "@okay": {}, + "validate": "Potvrdiť", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Vytvoriť", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Vyberte si potraviny, ktoré sú dobré pre vás a planétu.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Zobraziť údaje o potravinách, ktoré zodpovedajú vašim preferenciám.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Odkaz na aplikáciu Ceny na stránke produktu", "prices_app_button": "Prejdite do aplikácie Ceny", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Údaje", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Odfotiť", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sl.arb b/packages/smooth_app/lib/l10n/app_sl.arb index 9ee10bb3ca8..a63275bd19b 100644 --- a/packages/smooth_app/lib/l10n/app_sl.arb +++ b/packages/smooth_app/lib/l10n/app_sl.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "V redu", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Ustvari", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Izberite živila, ki je dobra za vas, kot tudi za svet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Oglejte si podatke o živilih, ki ustrezajo vašim željam.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Osveži fotografijo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Osveži fotografijo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Stanje", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Podatki", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Posnemi fotografijo", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sn.arb b/packages/smooth_app/lib/l10n/app_sn.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_sn.arb +++ b/packages/smooth_app/lib/l10n/app_sn.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_so.arb b/packages/smooth_app/lib/l10n/app_so.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_so.arb +++ b/packages/smooth_app/lib/l10n/app_so.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sq.arb b/packages/smooth_app/lib/l10n/app_sq.arb index 26aa2799529..d6113195a28 100644 --- a/packages/smooth_app/lib/l10n/app_sq.arb +++ b/packages/smooth_app/lib/l10n/app_sq.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ne rregull", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Shihni te dhenat ushqimore qe jane te rendesishme lidhur me pelqyeshmerite tuaja.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sr.arb b/packages/smooth_app/lib/l10n/app_sr.arb index bd2e6dd1d0f..e1bed265d04 100644 --- a/packages/smooth_app/lib/l10n/app_sr.arb +++ b/packages/smooth_app/lib/l10n/app_sr.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Подаци", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ss.arb b/packages/smooth_app/lib/l10n/app_ss.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_ss.arb +++ b/packages/smooth_app/lib/l10n/app_ss.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_st.arb b/packages/smooth_app/lib/l10n/app_st.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_st.arb +++ b/packages/smooth_app/lib/l10n/app_st.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sv.arb b/packages/smooth_app/lib/l10n/app_sv.arb index 6389bf35997..d66543e7895 100644 --- a/packages/smooth_app/lib/l10n/app_sv.arb +++ b/packages/smooth_app/lib/l10n/app_sv.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okej", "@okay": {}, + "validate": "Validera", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Skapa", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Se de matdata som är relevanta för dina önskemål.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ta en bild", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_sw.arb b/packages/smooth_app/lib/l10n/app_sw.arb index fab8450a8da..8dbf0d939b0 100644 --- a/packages/smooth_app/lib/l10n/app_sw.arb +++ b/packages/smooth_app/lib/l10n/app_sw.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ta.arb b/packages/smooth_app/lib/l10n/app_ta.arb index a3800c17a56..452c01bd7e4 100644 --- a/packages/smooth_app/lib/l10n/app_ta.arb +++ b/packages/smooth_app/lib/l10n/app_ta.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "சரி", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "உருவாக்கு", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "தரவு", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "ஒரு படம் எடு", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "இந்தப் புதிய அம்சத்தைப் பற்றிய உங்கள் கருத்தை எங்களுக்கு அனுப்ப இங்கே கிளிக் செய்யவும்!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_te.arb b/packages/smooth_app/lib/l10n/app_te.arb index 0c920c56da9..4aceca73a7d 100644 --- a/packages/smooth_app/lib/l10n/app_te.arb +++ b/packages/smooth_app/lib/l10n/app_te.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tg.arb b/packages/smooth_app/lib/l10n/app_tg.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_tg.arb +++ b/packages/smooth_app/lib/l10n/app_tg.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_th.arb b/packages/smooth_app/lib/l10n/app_th.arb index 6ab989ddbe1..7c896a7640b 100644 --- a/packages/smooth_app/lib/l10n/app_th.arb +++ b/packages/smooth_app/lib/l10n/app_th.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "โอเค", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "เลือกอาหาร ที่ดีสำหรับคุณ และโลกนี้", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "ดูข้อมูลอาหาร ที่คุณสนใจ(ความต้องการ)", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "ข้อมูล", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "ถ่ายภาพ", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2852,7 +2941,7 @@ "guide_nutriscore_v2_new_logo_title": "How to differentiate old Nutri-Score and new calculation?", "guide_nutriscore_v2_new_logo_text": "From now on, the logo can display a mention \"**New calculation**\" to clarify that this is indeed the new calculation.", "guide_nutriscore_v2_new_logo_image_caption": "The logo of the new Nutri-Score", - "guide_nutriscore_v2_where_title": "Where to find the new Nutri-Score calculation?", + "guide_nutriscore_v2_where_title": "ประเทศที่มีการนำ Nutri-Score แบบใหม่ไปใช้", "guide_nutriscore_v2_where_paragraph1": "The Nutri-Score is applied in several countries: Germany, Belgium, Spain, France, Luxembourg, the Netherlands and Switzerland.", "guide_nutriscore_v2_where_paragraph2": "Manufacturers have until **2026** at the latest **to replace** the old calculation with the new one.", "guide_nutriscore_v2_where_paragraph3": "Without waiting, you **will already find in the OpenFoodFacts application**, the new calculation, including if the manufacturers have not updated the score.", @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ti.arb b/packages/smooth_app/lib/l10n/app_ti.arb index d448c94a7d0..638bbf5a62b 100644 --- a/packages/smooth_app/lib/l10n/app_ti.arb +++ b/packages/smooth_app/lib/l10n/app_ti.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tl.arb b/packages/smooth_app/lib/l10n/app_tl.arb index dbcf11b0994..9b5d1efb91a 100644 --- a/packages/smooth_app/lib/l10n/app_tl.arb +++ b/packages/smooth_app/lib/l10n/app_tl.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Datos", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Kumuha ng larawan", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tn.arb b/packages/smooth_app/lib/l10n/app_tn.arb index 1e534e3b6c4..bcfa1f0af3a 100644 --- a/packages/smooth_app/lib/l10n/app_tn.arb +++ b/packages/smooth_app/lib/l10n/app_tn.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tr.arb b/packages/smooth_app/lib/l10n/app_tr.arb index 1ad5d380ce6..1bef3191f5c 100644 --- a/packages/smooth_app/lib/l10n/app_tr.arb +++ b/packages/smooth_app/lib/l10n/app_tr.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Tamam", "@okay": {}, + "validate": "Geçerlilik", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Oluştur", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Kendiniz ve gezegen için iyi olan yiyecekleri seçiniz.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Tercihleriniz ile ilgili gıda verilerine bakın.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Fotoğrafı yenileyin", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Fotoğrafı yenileyin", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Durum", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Ürün sayfasındaki Fiyatlar uygulamasının kısayolu", "prices_app_button": "Fiyatlar uygulamasına gidin", "prices_generic_title": "Fiyatlar", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Veri", @@ -2179,7 +2264,11 @@ }, "capture": "Yeni Yakala", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Resim çek", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Galeriden seç", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ts.arb b/packages/smooth_app/lib/l10n/app_ts.arb index 1e534e3b6c4..bcfa1f0af3a 100644 --- a/packages/smooth_app/lib/l10n/app_ts.arb +++ b/packages/smooth_app/lib/l10n/app_ts.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tt.arb b/packages/smooth_app/lib/l10n/app_tt.arb index 84cbf7f9024..4fd9ecd0870 100644 --- a/packages/smooth_app/lib/l10n/app_tt.arb +++ b/packages/smooth_app/lib/l10n/app_tt.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Ярар", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Ясарга", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Халәт", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Мәгълүмат", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_tw.arb b/packages/smooth_app/lib/l10n/app_tw.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_tw.arb +++ b/packages/smooth_app/lib/l10n/app_tw.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ty.arb b/packages/smooth_app/lib/l10n/app_ty.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_ty.arb +++ b/packages/smooth_app/lib/l10n/app_ty.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ug.arb b/packages/smooth_app/lib/l10n/app_ug.arb index facddd04004..39c0ace6eaf 100644 --- a/packages/smooth_app/lib/l10n/app_ug.arb +++ b/packages/smooth_app/lib/l10n/app_ug.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "سانلىق مەلۇمات", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "رەسىمگە تارتىش", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uk.arb b/packages/smooth_app/lib/l10n/app_uk.arb index bdc0ab8d9a3..ad3b7af325c 100644 --- a/packages/smooth_app/lib/l10n/app_uk.arb +++ b/packages/smooth_app/lib/l10n/app_uk.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Перевірити", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Створити", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Обирайте їжу, що не шкодить ні Вам, ні планеті.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Продивіться дані про харчові продукти, що відповідають вашим вподобанням.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Чому я бачу це повідомлення?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "Щоб скористатися функцією «Витяг інгредієнтів», спершу потрібно завантажити фото.\n\nЗачекайте кілька секунд або введіть їх вручну.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Оновити фото", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Чому я бачу це повідомлення?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "Щоб скористатися функцією «Витягнути упаковку», спочатку потрібно завантажити фотографію.\n\nЗачекайте кілька секунд або введіть їх вручну.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Оновити фото", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Стан", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Ярлик програми «Ціни» на сторінці продукту", "prices_app_button": "Перейдіть у додаток Ціни", "prices_generic_title": "Ціни", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Сканер штрих-коду", "prices_view_prices": "Переглянути ціни", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Конфігурація сервера", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Сторінка продукту", "dev_mode_section_ui": "Інтерфейс користувача", "dev_mode_section_data": "Дані", @@ -2179,7 +2264,11 @@ }, "capture": "Зробити нове фото", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Сфотографувати", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Вибрати з галереї", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Попередній перегляд", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Натисніть тут, щоб надіслати нам свій відгук про цю нову функцію!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ur.arb b/packages/smooth_app/lib/l10n/app_ur.arb index a050e760be7..ec48fadb2d6 100644 --- a/packages/smooth_app/lib/l10n/app_ur.arb +++ b/packages/smooth_app/lib/l10n/app_ur.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "تصویر لیں", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_uz.arb b/packages/smooth_app/lib/l10n/app_uz.arb index a10381b1069..391c0e2d8cf 100644 --- a/packages/smooth_app/lib/l10n/app_uz.arb +++ b/packages/smooth_app/lib/l10n/app_uz.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Maʻlumot", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Suratga olish", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_ve.arb b/packages/smooth_app/lib/l10n/app_ve.arb index 1e534e3b6c4..bcfa1f0af3a 100644 --- a/packages/smooth_app/lib/l10n/app_ve.arb +++ b/packages/smooth_app/lib/l10n/app_ve.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_vi.arb b/packages/smooth_app/lib/l10n/app_vi.arb index 2f38a26f8d9..5ce19b4332f 100644 --- a/packages/smooth_app/lib/l10n/app_vi.arb +++ b/packages/smooth_app/lib/l10n/app_vi.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Xác thực", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Tạo", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Lựa chọn thực phẩm tốt cho bạn và hành tinh này.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "Xem dữ liệu thực phẩm liên quan đến sở thích của bạn.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Làm mới ảnh", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Làm mới ảnh", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Trạng thái", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Dữ liệu", @@ -2179,7 +2264,11 @@ }, "capture": "Chụp mới", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Chụp ảnh", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Chọn từ thư viện ảnh", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wa.arb b/packages/smooth_app/lib/l10n/app_wa.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_wa.arb +++ b/packages/smooth_app/lib/l10n/app_wa.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_wo.arb b/packages/smooth_app/lib/l10n/app_wo.arb index 1e534e3b6c4..bcfa1f0af3a 100644 --- a/packages/smooth_app/lib/l10n/app_wo.arb +++ b/packages/smooth_app/lib/l10n/app_wo.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_xh.arb b/packages/smooth_app/lib/l10n/app_xh.arb index cc3ec58afc4..54a17cba161 100644 --- a/packages/smooth_app/lib/l10n/app_xh.arb +++ b/packages/smooth_app/lib/l10n/app_xh.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yi.arb b/packages/smooth_app/lib/l10n/app_yi.arb index d880cf68188..a04870a85f2 100644 --- a/packages/smooth_app/lib/l10n/app_yi.arb +++ b/packages/smooth_app/lib/l10n/app_yi.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_yo.arb b/packages/smooth_app/lib/l10n/app_yo.arb index c1cd3ac71e0..c1194b8140c 100644 --- a/packages/smooth_app/lib/l10n/app_yo.arb +++ b/packages/smooth_app/lib/l10n/app_yo.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Ya aworan kan", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zh.arb b/packages/smooth_app/lib/l10n/app_zh.arb index 4dd46edf3f7..a0a0a0069c0 100644 --- a/packages/smooth_app/lib/l10n/app_zh.arb +++ b/packages/smooth_app/lib/l10n/app_zh.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "好的", "@okay": {}, + "validate": "驗證", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "创建", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "选择对您和地球有益的食物。", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "查看和您的偏好有关的食品数据。", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "刷新照片", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "刷新照片", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "狀態", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "數據", @@ -2179,7 +2264,11 @@ }, "capture": "拍摄", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "選一張圖片", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "从相册选择", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/l10n/app_zu.arb b/packages/smooth_app/lib/l10n/app_zu.arb index 0fc7d7f6c74..f883d66d9f2 100644 --- a/packages/smooth_app/lib/l10n/app_zu.arb +++ b/packages/smooth_app/lib/l10n/app_zu.arb @@ -14,6 +14,10 @@ "@reason": {}, "okay": "Okay", "@okay": {}, + "validate": "Validate", + "@validate": { + "description": "Button label: Validate the input" + }, "create": "Create", "@create": { "description": "An action to create" @@ -129,10 +133,6 @@ "@whatIsOff": { "description": "Description of Open Food Facts organization." }, - "offUtility": "Choose food that is good for you and the planet.", - "@offUtility": { - "description": "Description of what a user can use Open Food Facts for." - }, "productDataUtility": "See the food data relevant to your preferences.", "@productDataUtility": { "description": "Description of what a user can use the product data for." @@ -1491,6 +1491,14 @@ "@edit_ingredients_loading_photo_btn_text": { "description": "Ingredients edition - Loading photo from the server" }, + "edit_ingredients_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_ingredients_loading_photo_help_dialog_title": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Title" + }, + "edit_ingredients_loading_photo_help_dialog_body": "To use the \"Extract ingredients\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_ingredients_loading_photo_help_dialog_body": { + "description": "Ingredients edition - Dialog explaining why the photo is loading - Content" + }, "edit_ingredients_refresh_photo_btn_text": "Refresh photo", "@edit_ingredients_refresh_photo_btn_text": { "description": "Ingredients edition - Refresh photo" @@ -1507,6 +1515,14 @@ "@edit_packaging_loading_photo_btn_text": { "description": "Packaging edition - Loading photo from the server" }, + "edit_packaging_loading_photo_help_dialog_title": "Why do I see this message?", + "@edit_packaging_loading_photo_help_dialog_title": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Title" + }, + "edit_packaging_loading_photo_help_dialog_body": "To use the \"Extract packaging\" feature, the photo needs to be uploaded first.\n\nPlease wait a few seconds or enter them manually.", + "@edit_packaging_loading_photo_help_dialog_body": { + "description": "Packaging edition - Dialog explaining why the photo is loading - Content" + }, "edit_packaging_refresh_photo_btn_text": "Refresh photo", "@edit_packaging_refresh_photo_btn_text": { "description": "Packaging edition - Refresh photo" @@ -1716,6 +1732,31 @@ "@dev_preferences_import_history_subtitle": { "description": "User dev preferences - Import history - Subtitle" }, + "dev_preferences_news_custom_url_title": "Custom URL for news", + "@dev_preferences_news_custom_url_title": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_subtitle": "URL of the JSON file:", + "@dev_preferences_news_custom_url_subtitle": { + "description": "News dev preferences - Custom URL for news - Title" + }, + "dev_preferences_news_custom_url_empty_value": "Not set", + "@dev_preferences_news_custom_url_empty_value": { + "description": "Message to show when the custom news URL is not set" + }, + "dev_preferences_news_provider_status_title": "Status", + "@dev_preferences_news_provider_status_title": { + "description": "News dev preferences - Status - Title" + }, + "dev_preferences_news_provider_status_subtitle": "Last refresh: {date}", + "@dev_preferences_news_provider_status_subtitle": { + "description": "News dev preferences - Custom URL for news - Subtitle", + "placeholders": { + "date": { + "type": "String" + } + } + }, "prices_app_dev_mode_flag": "Shortcut to Prices app on product page", "prices_app_button": "Go to Prices app", "prices_generic_title": "Prices", @@ -1740,6 +1781,18 @@ }, "prices_barcode_reader_action": "Barcode reader", "prices_view_prices": "View the prices", + "prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}", + "@prices_product_accessibility_summary": { + "description": "A card summarizing the number of prices for a product", + "placeholders": { + "count": { + "type": "int" + }, + "product": { + "type": "String" + } + } + }, "prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", @@ -1761,6 +1814,37 @@ } } }, + "prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"", + "@prices_entry_accessibility_label": { + "description": "Accessibility label for a price entry", + "placeholders": { + "price": { + "type": "String" + }, + "location": { + "type": "String" + }, + "date": { + "type": "String" + }, + "user": { + "type": "String" + } + } + }, + "prices_open_user_proofs": "Open proofs of \"{user}\"", + "@prices_open_user_proofs": { + "description": "Button to open the proofs of a user", + "placeholders": { + "user": { + "type": "String" + } + } + }, + "prices_open_proof": "Open price proof", + "@prices_open_proof": { + "description": "Button to open a proof" + }, "prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", @@ -1824,6 +1908,7 @@ "description": "User dev preferences - Import history - Result successful" }, "dev_mode_section_server": "Server configuration", + "dev_mode_section_news": "News provider configuration", "dev_mode_section_product_page": "Product page", "dev_mode_section_ui": "User Interface", "dev_mode_section_data": "Data", @@ -2179,7 +2264,11 @@ }, "capture": "Capture New", "@capture": { - "description": "Button label for taking a photo" + "description": "Button label for taking a new photo (= there's already one)" + }, + "capture_new_picture": "Take a picture", + "@capture_new_picture": { + "description": "Button label for taking a new photo (= the first one)" }, "choose_from_gallery": "Choose from gallery", "@choose_from_gallery": { @@ -2867,5 +2956,9 @@ "preview_badge": "Preview", "@preview_badge": { "description": "Badge to indicate that the product is in preview mode (Be careful with this translation)" + }, + "prices_feedback_form": "Click here to send us your feedback about this new feature!", + "@prices_feedback_form": { + "description": "A button to send feedback about the prices feature" } } \ No newline at end of file From 737d3591dee4082f031d927424f939a9a17862ab Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Sun, 21 Jul 2024 13:43:49 +0200 Subject: [PATCH 73/85] fix: plurals for hebrew and dutch (#5496) --- packages/smooth_app/lib/l10n/app_he.arb | 6 +++--- packages/smooth_app/lib/l10n/app_nl.arb | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/smooth_app/lib/l10n/app_he.arb b/packages/smooth_app/lib/l10n/app_he.arb index 68b6239d5e8..e48b6b10fee 100644 --- a/packages/smooth_app/lib/l10n/app_he.arb +++ b/packages/smooth_app/lib/l10n/app_he.arb @@ -1760,8 +1760,8 @@ "prices_app_dev_mode_flag": "קיצור דרך ליישומון מחירים בעמוד המוצר", "prices_app_button": "מעבר ליישומון המחירים", "prices_generic_title": "מחירים", - "prices_add_n_prices": "{count,plural, one {} two {הוספת {count} מחירים} many {הוספת {count} מחירים}=1{הוספת מחיר{count}} other{הוספת {count} מחירים}}", - "prices_send_n_prices": "{count,plural, one {} two {שליחת {count} מחירים} many {שליחת {count} מחירים}=1{שליחת מחיר {count}} other{שליחת {count} מחירים}}", + "prices_add_n_prices": "{count,plural, two {הוספת {count} מחירים} many {הוספת {count} מחירים}=1{הוספת מחיר{count}} other{הוספת {count} מחירים}}", + "prices_send_n_prices": "{count,plural, two {שליחת {count} מחירים} many {שליחת {count} מחירים}=1{שליחת מחיר {count}} other{שליחת {count} מחירים}}", "prices_add_an_item": "הוספת פריט", "prices_add_a_price": "הוספת מחיר", "prices_add_a_receipt": "הוספת קבלה", @@ -1781,7 +1781,7 @@ }, "prices_barcode_reader_action": "קורא ברקודים", "prices_view_prices": "הצגת המחירים", - "prices_product_accessibility_summary": "{count,plural, one {} two {{count} מחירים} many {{count} מחירים}=1{מחיר {count}} other{{count} מחירים}} ל{product}", + "prices_product_accessibility_summary": "{count,plural, two {{count} מחירים} many {{count} מחירים}=1{מחיר {count}} other{{count} מחירים}} ל{product}", "@prices_product_accessibility_summary": { "description": "A card summarizing the number of prices for a product", "placeholders": { diff --git a/packages/smooth_app/lib/l10n/app_nl.arb b/packages/smooth_app/lib/l10n/app_nl.arb index d444cb76771..354501db98a 100644 --- a/packages/smooth_app/lib/l10n/app_nl.arb +++ b/packages/smooth_app/lib/l10n/app_nl.arb @@ -1760,8 +1760,8 @@ "prices_app_dev_mode_flag": "Snelkoppeling naar de Prijzen-app op de productpagina", "prices_app_button": "Ga naar de Prijzen-app", "prices_generic_title": "Prijzen", - "prices_add_n_prices": "{count,plural, one {}=1{Voeg 1 prijs toe} other{Voeg {count} prijzen toe}}", - "prices_send_n_prices": "{count,plural, one {}=1{Verstuur 1 prijs} other{Verstuur {count} prijzen}}", + "prices_add_n_prices": "{count,plural, =1{Voeg 1 prijs toe} other{Voeg {count} prijzen toe}}", + "prices_send_n_prices": "{count,plural, =1{Verstuur 1 prijs} other{Verstuur {count} prijzen}}", "prices_add_an_item": "Item toevoegen", "prices_add_a_price": "Voeg een prijs toe", "prices_add_a_receipt": "Een ontvangstbewijs toevoegen", @@ -1781,7 +1781,7 @@ }, "prices_barcode_reader_action": "Streepjescodelezer", "prices_view_prices": "Bekijk de prijzen", - "prices_product_accessibility_summary": "{count,plural, one {}=1{1 prijs} other{{count} prijzen}} voor {product}", + "prices_product_accessibility_summary": "{count,plural, =1{1 prijs} other{{count} prijzen}} voor {product}", "@prices_product_accessibility_summary": { "description": "A card summarizing the number of prices for a product", "placeholders": { @@ -1793,7 +1793,7 @@ } } }, - "prices_list_length_one_page": "{count,plural, one {}=0{Nog geen prijs} =1{Slechts één prijs} other{Alle {count} prijzen}}", + "prices_list_length_one_page": "{count,plural, =0{Nog geen prijs} =1{Slechts één prijs} other{Alle {count} prijzen}}", "@prices_list_length_one_page": { "description": "Number of prices for one-page result", "placeholders": { @@ -1845,7 +1845,7 @@ "@prices_open_proof": { "description": "Button to open a proof" }, - "prices_proofs_list_length_one_page": "{count,plural, one {}=0{Nog geen bewijs} =1{Slechts één bewijs} other{Alle {count} bewijzen}}", + "prices_proofs_list_length_one_page": "{count,plural, =0{Nog geen bewijs} =1{Slechts één bewijs} other{Alle {count} bewijzen}}", "@prices_proofs_list_length_one_page": { "description": "Number of proofs for one-page result", "placeholders": { From 1f9caa2b0c1cd2e516584f9221bc9b2a36df5e2c Mon Sep 17 00:00:00 2001 From: Pierre Slamich Date: Mon, 22 Jul 2024 09:19:19 +0200 Subject: [PATCH 74/85] ci: Update crowdin.yml --- crowdin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/crowdin.yml b/crowdin.yml index 2a1c9fb1819..0a1c3d77355 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -2,6 +2,7 @@ project_id_env: CROWDIN_PROJECT_ID api_token_env: CROWDIN_PERSONAL_TOKEN pull_request_title: "chore: New translations to review and merge" pull_request_body: '### What\n- Automated pull request pulling in new or updated translations from Crowdin (https://translate.openfoodfacts.org).\n## Checklist\n- [ ] Check that they are no bad translations. If there are, correct them directly in Crowdin so that they are not resynced again. Then you can correct them here as well, or wait 24 hours for the sync to happen automatically.\n- [ ] Put extra attention on Acholi, which is used mistakenly as a sandbox by people discovering the self-service translation button on Open Food Facts\n- [ ] Once you are happy, that automated checks pass, you can approve the PR and merge it.\n### Part of\n- Translations' +pull_request_labels : 'translations' files: - source: /packages/smooth_app/lib/l10n/app_en.arb dist: /packages/smooth_app/lib/l10n/app_en.arb From a9e216c72d467533da9ea815eb69131f5cc909bf Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 22 Jul 2024 10:50:43 +0200 Subject: [PATCH 75/85] feat: Popup Menu now uses the iOS actions sheet (#5494) * iOS popup menu (cherry picked from commit 493f3d2ebbf444579f8c03ff0ac7d5f8b9db55e7) * Reorder mandatory fields --- packages/smooth_app/lib/l10n/app_en.arb | 4 + .../lib/pages/personalized_ranking_page.dart | 9 +- .../common/product_list_item_popup_items.dart | 18 ++- .../product/common/product_list_page.dart | 11 +- .../common/product_list_popup_items.dart | 18 ++- .../lib/widgets/smooth_menu_button.dart | 118 ++++++++++++++++++ packages/smooth_app/macos/Podfile.lock | 2 +- 7 files changed, 157 insertions(+), 23 deletions(-) create mode 100644 packages/smooth_app/lib/widgets/smooth_menu_button.dart diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 4950480c499..01a2f992a77 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -2960,5 +2960,9 @@ "prices_feedback_form": "Click here to send us your feedback about this new feature!", "@prices_feedback_form": { "description": "A button to send feedback about the prices feature" + }, + "menu_button_list_actions": "Select an action", + "@menu_button_list_actions": { + "description": "Button to select an action in a list (eg: Share, Delete, …)" } } \ No newline at end of file diff --git a/packages/smooth_app/lib/pages/personalized_ranking_page.dart b/packages/smooth_app/lib/pages/personalized_ranking_page.dart index 4b6d42ea9d8..8441d94c516 100644 --- a/packages/smooth_app/lib/pages/personalized_ranking_page.dart +++ b/packages/smooth_app/lib/pages/personalized_ranking_page.dart @@ -16,6 +16,7 @@ import 'package:smooth_app/pages/product/common/loading_status.dart'; import 'package:smooth_app/pages/product/common/product_list_item_simple.dart'; import 'package:smooth_app/pages/product_list_user_dialog_helper.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_menu_button.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; class PersonalizedRankingPage extends StatefulWidget { @@ -97,13 +98,13 @@ class _PersonalizedRankingPageState extends State appBar: SmoothAppBar( title: Text(widget.title, overflow: TextOverflow.fade), actions: [ - PopupMenuButton( + SmoothPopupMenuButton( onSelected: _handlePopUpClick, itemBuilder: (BuildContext context) { - return >[ - PopupMenuItem( + return >[ + SmoothPopupMenuItem( value: 'add_to_list', - child: Text(appLocalizations.user_list_button_add_product), + label: appLocalizations.user_list_button_add_product, ), ]; }, diff --git a/packages/smooth_app/lib/pages/product/common/product_list_item_popup_items.dart b/packages/smooth_app/lib/pages/product/common/product_list_item_popup_items.dart index b97f58f32b0..ed67bb929bd 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_item_popup_items.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_item_popup_items.dart @@ -10,6 +10,7 @@ import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/pages/personalized_ranking_page.dart'; import 'package:smooth_app/pages/product/compare_products3_page.dart'; import 'package:smooth_app/pages/product/ordered_nutrients_cache.dart'; +import 'package:smooth_app/widgets/smooth_menu_button.dart'; /// Popup menu item entries for the product list page, for selected items. enum ProductListItemPopupMenuEntry { @@ -26,6 +27,9 @@ abstract class ProductListItemPopupItem { /// IconData of the popup menu item. IconData getIconData(); + /// Is-it a destructive action? + bool isDestructive() => false; + /// Action of the popup menu item. /// /// Returns true if the caller must refresh (setState) (e.g. after deleting). @@ -37,17 +41,16 @@ abstract class ProductListItemPopupItem { }); /// Returns the popup menu item. - PopupMenuItem getMenuItem( + SmoothPopupMenuItem getMenuItem( final AppLocalizations appLocalizations, final bool enabled, ) => - PopupMenuItem( + SmoothPopupMenuItem( value: this, + icon: getIconData(), + label: getTitle(appLocalizations), enabled: enabled, - child: ListTile( - leading: Icon(getIconData()), - title: Text(getTitle(appLocalizations)), - ), + type: isDestructive() ? SmoothPopupMenuItemType.destructive : null, ); } @@ -139,6 +142,9 @@ class ProductListItemPopupDelete extends ProductListItemPopupItem { @override IconData getIconData() => Icons.delete; + @override + bool isDestructive() => true; + @override Future doSomething({ required final ProductList productList, diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index 59d9b4e671a..2336258b8a8 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -31,6 +31,7 @@ import 'package:smooth_app/pages/product_list_user_dialog_helper.dart'; import 'package:smooth_app/pages/scan/carousel/scan_carousel_manager.dart'; import 'package:smooth_app/query/product_query.dart'; import 'package:smooth_app/widgets/smooth_app_bar.dart'; +import 'package:smooth_app/widgets/smooth_menu_button.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; import 'package:smooth_app/widgets/will_pop_scope.dart'; @@ -181,7 +182,7 @@ class _ProductListPageState extends State } }, ), - PopupMenuButton( + SmoothPopupMenuButton( onSelected: (final ProductListPopupItem action) async { final ProductList? differentProductList = await action.doSomething( @@ -193,8 +194,7 @@ class _ProductListPageState extends State setState(() => productList = differentProductList); } }, - itemBuilder: (BuildContext context) => - >[ + itemBuilder: (_) => >[ if (enableRename) _rename.getMenuItem(appLocalizations), _share.getMenuItem(appLocalizations), _openInWeb.getMenuItem(appLocalizations), @@ -215,7 +215,7 @@ class _ProductListPageState extends State }, actionModeTitle: Text('${_selectedBarcodes.length}'), actionModeActions: [ - PopupMenuButton( + SmoothPopupMenuButton( onSelected: (final ProductListItemPopupItem action) async { final bool andThenSetState = await action.doSomething( productList: productList, @@ -229,8 +229,7 @@ class _ProductListPageState extends State } } }, - itemBuilder: (BuildContext context) => - >[ + itemBuilder: (_) => >[ if (userPreferences.getFlag(UserPreferencesDevMode .userPreferencesFlagBoostedComparison) == true) diff --git a/packages/smooth_app/lib/pages/product/common/product_list_popup_items.dart b/packages/smooth_app/lib/pages/product/common/product_list_popup_items.dart index 8fdcbd345d9..fbbd20e1796 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_popup_items.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_popup_items.dart @@ -8,6 +8,7 @@ import 'package:smooth_app/generic_lib/dialogs/smooth_alert_dialog.dart'; import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/temp_product_list_share_helper.dart'; import 'package:smooth_app/pages/product_list_user_dialog_helper.dart'; +import 'package:smooth_app/widgets/smooth_menu_button.dart'; import 'package:url_launcher/url_launcher.dart'; /// Popup menu item entries for the product list page. @@ -30,6 +31,9 @@ abstract class ProductListPopupItem { /// Popup menu entry of the popup menu item. ProductListPopupMenuEntry getEntry(); + /// Is-it a destructive action? + bool isDestructive() => false; + /// Action of the popup menu item. /// /// Returns a different product list if there are changes, else null. @@ -40,15 +44,14 @@ abstract class ProductListPopupItem { }); /// Returns the popup menu item. - PopupMenuItem getMenuItem( + SmoothPopupMenuItem getMenuItem( final AppLocalizations appLocalizations, ) => - PopupMenuItem( + SmoothPopupMenuItem( value: this, - child: ListTile( - leading: Icon(getIconData()), - title: Text(getTitle(appLocalizations)), - ), + icon: getIconData(), + label: getTitle(appLocalizations), + type: isDestructive() ? SmoothPopupMenuItemType.destructive : null, ); } @@ -64,6 +67,9 @@ class ProductListPopupClear extends ProductListPopupItem { @override ProductListPopupMenuEntry getEntry() => ProductListPopupMenuEntry.clear; + @override + bool isDestructive() => true; + @override Future doSomething({ required final ProductList productList, diff --git a/packages/smooth_app/lib/widgets/smooth_menu_button.dart b/packages/smooth_app/lib/widgets/smooth_menu_button.dart new file mode 100644 index 00000000000..0485b522183 --- /dev/null +++ b/packages/smooth_app/lib/widgets/smooth_menu_button.dart @@ -0,0 +1,118 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +/// A Button similar to a [PopupMenuButton] for non Apple platforms. +/// On iOS and macOS, it's still an [IconButton], but that opens a +/// [CupertinoActionSheet]. +class SmoothPopupMenuButton extends StatefulWidget { + const SmoothPopupMenuButton({ + required this.onSelected, + required this.itemBuilder, + this.actionsTitle, + this.buttonIcon, + this.buttonLabel, + }) : assert(buttonLabel == null || buttonLabel.length > 0), + assert(actionsTitle == null || actionsTitle.length > 0); + + final void Function(T value) onSelected; + final Iterable> Function(BuildContext context) + itemBuilder; + final Icon? buttonIcon; + final String? buttonLabel; + final String? actionsTitle; + + @override + State> createState() => + _SmoothPopupMenuButtonState(); +} + +class _SmoothPopupMenuButtonState extends State> { + @override + Widget build(BuildContext context) { + if (Platform.isIOS || Platform.isMacOS) { + return IconButton( + icon: widget.buttonIcon ?? Icon(Icons.adaptive.more), + tooltip: widget.buttonLabel ?? + MaterialLocalizations.of(context).showMenuTooltip, + onPressed: _openModalSheet, + ); + } else { + return PopupMenuButton( + icon: widget.buttonIcon ?? Icon(Icons.adaptive.more), + tooltip: widget.buttonLabel ?? + MaterialLocalizations.of(context).showMenuTooltip, + onSelected: widget.onSelected, + itemBuilder: (BuildContext context) { + return widget.itemBuilder(context).map((SmoothPopupMenuItem item) { + return PopupMenuItem( + value: item.value, + enabled: item.enabled, + child: ListTile( + leading: Icon(item.icon), + title: Text(item.label), + ), + ); + }).toList(growable: false); + }, + ); + } + } + + // iOS and macOS behavior + void _openModalSheet() { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return CupertinoActionSheet( + title: Text( + widget.actionsTitle ?? + AppLocalizations.of(context).menu_button_list_actions, + ), + actions: widget + .itemBuilder(context) + .where((SmoothPopupMenuItem item) => item.enabled) + .map((SmoothPopupMenuItem item) { + return CupertinoActionSheetAction( + isDefaultAction: + item.type == SmoothPopupMenuItemType.highlighted, + isDestructiveAction: + item.type == SmoothPopupMenuItemType.destructive, + onPressed: () { + widget.onSelected(item.value); + Navigator.of(context).maybePop(); + }, + child: Text(item.label), + ); + }).toList(growable: false), + ); + }); + } +} + +class SmoothPopupMenuItem { + const SmoothPopupMenuItem({ + required this.value, + required this.label, + this.icon, + this.type, + this.enabled = true, + }) : assert(label.length > 0); + + final T value; + final String label; + final IconData? icon; + final SmoothPopupMenuItemType? type; + final bool enabled; +} + +/// The style of an item in the menu +/// On Material platforms, all values behave the same. +/// On iOS, the [highlighted] value is in black and [destructive] in red. +enum SmoothPopupMenuItemType { + normal, + highlighted, + destructive, +} diff --git a/packages/smooth_app/macos/Podfile.lock b/packages/smooth_app/macos/Podfile.lock index a01e826ae0d..c802b6a34ca 100644 --- a/packages/smooth_app/macos/Podfile.lock +++ b/packages/smooth_app/macos/Podfile.lock @@ -114,7 +114,7 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 mobile_scanner: 54ceceae0c8da2457e26a362a6be5c61154b1829 - package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce + package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 ReachabilitySwift: 2128f3a8c9107e1ad33574c6e58e8285d460b149 rive_common: cf5ab646aa576b2d742d0e2d528126fbf032c856 From a797ebde6de4d0d2a1496e0a8145618d836346cb Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Mon, 22 Jul 2024 12:13:01 +0200 Subject: [PATCH 76/85] feat: Add the outdated indicator to the photo grid (#5491) * Add the outdated indicator to the photo grid * Add some comments --- .../lib/data_models/product_image_data.dart | 2 + .../lib/database/transient_file.dart | 43 ++++--- .../lib/helpers/product_cards_helper.dart | 2 + packages/smooth_app/lib/l10n/app_en.arb | 7 ++ .../lib/pages/image/product_image_helper.dart | 23 ++++ .../lib/pages/image/product_image_widget.dart | 7 +- .../product/product_image_gallery_view.dart | 108 +++++++++++------- 7 files changed, 133 insertions(+), 59 deletions(-) create mode 100644 packages/smooth_app/lib/pages/image/product_image_helper.dart diff --git a/packages/smooth_app/lib/data_models/product_image_data.dart b/packages/smooth_app/lib/data_models/product_image_data.dart index c11f2bc1e25..9aaa20fd227 100644 --- a/packages/smooth_app/lib/data_models/product_image_data.dart +++ b/packages/smooth_app/lib/data_models/product_image_data.dart @@ -2,11 +2,13 @@ import 'package:openfoodfacts/openfoodfacts.dart'; class ProductImageData { const ProductImageData({ + required this.imageId, required this.imageField, required this.imageUrl, required this.language, }); + final String? imageId; final ImageField imageField; final String? imageUrl; final OpenFoodFactsLanguage? language; diff --git a/packages/smooth_app/lib/database/transient_file.dart b/packages/smooth_app/lib/database/transient_file.dart index dedaa7436d8..90714684c12 100644 --- a/packages/smooth_app/lib/database/transient_file.dart +++ b/packages/smooth_app/lib/database/transient_file.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/data_models/product_image_data.dart'; @@ -11,34 +12,48 @@ class TransientFile { TransientFile( this.imageField, this.barcode, - this.language, - ) : url = null; + this.language, [ + this.uploadedDate, + ]) : url = null; TransientFile.fromProductImageData( final ProductImageData productImageData, this.barcode, - this.language, - ) : imageField = productImageData.imageField, + this.language, [ + this.uploadedDate, + ]) : imageField = productImageData.imageField, url = productImageData.imageUrl; - TransientFile.fromProduct( + factory TransientFile.fromProduct( final Product product, final ImageField imageField, final OpenFoodFactsLanguage language, - ) : this.fromProductImageData( - getProductImageData( - product, - imageField, - language, - ), - product.barcode!, - language, - ); + ) { + final ProductImageData productImageData = getProductImageData( + product, + imageField, + language, + ); + + return TransientFile.fromProductImageData( + productImageData, + product.barcode!, + language, + product + .getRawImages() + ?.firstWhereOrNull( + (final ProductImage productImage) => + productImage.imgid == productImageData.imageId, + ) + ?.uploaded, + ); + } final ImageField imageField; final String barcode; final OpenFoodFactsLanguage language; final String? url; + final DateTime? uploadedDate; /// {File "key": file path} map. static final Map _transientFiles = {}; diff --git a/packages/smooth_app/lib/helpers/product_cards_helper.dart b/packages/smooth_app/lib/helpers/product_cards_helper.dart index cf8553433f3..c229ad58177 100644 --- a/packages/smooth_app/lib/helpers/product_cards_helper.dart +++ b/packages/smooth_app/lib/helpers/product_cards_helper.dart @@ -266,6 +266,7 @@ ProductImageData getProductImageData( if (productImage != null) { // we found a localized version for this image return ProductImageData( + imageId: productImage.imgid, imageField: imageField, imageUrl: productImage.getUrl( product.barcode!, @@ -281,6 +282,7 @@ ProductImageData getProductImageData( ProductImageData getEmptyProductImageData(final ImageField imageField) => ProductImageData( imageField: imageField, + imageId: null, imageUrl: null, language: null, ); diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 01a2f992a77..fac43512480 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -514,6 +514,13 @@ "@front_photo": { "description": "Button label: For adding a picture of the front of a product" }, + "outdated_image_accessibility_label": "{imageType} (this image may be outdated)", + "@outdated_image_accessibility_label": { + "description": "Accessibility label for images that are outdated (image type may be front/ingredients/nutrition…)", + "placeholders": { + "imageType": {} + } + }, "ingredients": "Ingredients", "@ingredients": {}, "ingredients_editing_instructions": "Keep the original order. Indicate the percentage when specified. Separate with a comma or hyphen, use parentheses for ingredients of an ingredient, and indicate allergens between underscores.", diff --git a/packages/smooth_app/lib/pages/image/product_image_helper.dart b/packages/smooth_app/lib/pages/image/product_image_helper.dart new file mode 100644 index 00000000000..6ef986950f0 --- /dev/null +++ b/packages/smooth_app/lib/pages/image/product_image_helper.dart @@ -0,0 +1,23 @@ +import 'package:openfoodfacts/openfoodfacts.dart'; +import 'package:smooth_app/database/transient_file.dart'; + +class _ProductImageHelper { + const _ProductImageHelper._(); + + /// An image is considered outdated/expired after 1 year. + /// Note: the value will be sent in the future by the backend. + static bool isExpired(final DateTime? uploadedDate) { + if (uploadedDate == null) { + return false; + } + return DateTime.now().difference(uploadedDate).inDays > 365; + } +} + +extension ProductImageExtension on ProductImage { + bool get expired => _ProductImageHelper.isExpired(uploaded); +} + +extension TransientFileExtension on TransientFile { + bool get expired => _ProductImageHelper.isExpired(uploadedDate); +} diff --git a/packages/smooth_app/lib/pages/image/product_image_widget.dart b/packages/smooth_app/lib/pages/image/product_image_widget.dart index 50dd84ded55..7393a6bd841 100644 --- a/packages/smooth_app/lib/pages/image/product_image_widget.dart +++ b/packages/smooth_app/lib/pages/image/product_image_widget.dart @@ -6,8 +6,9 @@ import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; import 'package:smooth_app/generic_lib/widgets/images/smooth_image.dart'; import 'package:smooth_app/generic_lib/widgets/smooth_card.dart'; +import 'package:smooth_app/pages/image/product_image_helper.dart'; import 'package:smooth_app/query/product_query.dart'; -import 'package:smooth_app/resources/app_icons.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; import 'package:smooth_app/themes/smooth_theme_colors.dart'; /// Displays a product image thumbnail with the upload date on top. @@ -52,7 +53,7 @@ class ProductImageWidget extends StatelessWidget { if (uploaded == null) { return image; } - final bool expired = DateTime.now().difference(uploaded).inDays > 365; + final bool expired = productImage.expired; final String date = dateFormat.format(uploaded); return Semantics( @@ -94,7 +95,7 @@ class ProductImageWidget extends StatelessWidget { end: 0.0, height: 20.0, textDirection: Directionality.of(context), - child: Outdated( + child: icons.Outdated( size: 18.0, color: colors.red, ), diff --git a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart index 26197d46234..c517696c74e 100644 --- a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart +++ b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart @@ -13,11 +13,13 @@ import 'package:smooth_app/helpers/analytics_helper.dart'; import 'package:smooth_app/helpers/image_field_extension.dart'; import 'package:smooth_app/helpers/product_cards_helper.dart'; import 'package:smooth_app/pages/image/product_image_gallery_other_view.dart'; +import 'package:smooth_app/pages/image/product_image_helper.dart'; import 'package:smooth_app/pages/image_crop_page.dart'; import 'package:smooth_app/pages/product/common/product_refresher.dart'; import 'package:smooth_app/pages/product/product_image_swipeable_view.dart'; import 'package:smooth_app/query/product_query.dart'; import 'package:smooth_app/resources/app_animations.dart'; +import 'package:smooth_app/resources/app_icons.dart' as icons; import 'package:smooth_app/widgets/slivers.dart'; import 'package:smooth_app/widgets/smooth_scaffold.dart'; @@ -193,50 +195,72 @@ class _PhotoRow extends StatelessWidget { final ImageField imageField = _getImageField(position); final TransientFile transientFile = _getTransientFile(imageField); - return Padding( - padding: const EdgeInsets.only( - top: SMALL_SPACE, - ), - child: InkWell( - onTap: () => _openImage( - context: context, - initialImageIndex: position, + final bool expired = transientFile.expired; + + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final String label = imageField.getProductImageTitle(appLocalizations); + + return Semantics( + image: true, + button: true, + label: expired + ? appLocalizations.product_image_outdated_accessibility_label(label) + : label, + excludeSemantics: true, + child: Padding( + padding: const EdgeInsets.only( + top: SMALL_SPACE, ), - child: Column( - children: [ - Stack( - children: [ - AspectRatio( - aspectRatio: 1.0, - child: SmoothImage( - rounded: false, - imageProvider: transientFile.getImageProvider(), - ), - ), - if (transientFile.isImageAvailable() && - !transientFile.isServerImage()) - Positioned.directional( - textDirection: Directionality.of(context), - bottom: VERY_SMALL_SPACE, - end: VERY_SMALL_SPACE, - child: const CloudUploadAnimation.circle(size: 30.0), + child: InkWell( + onTap: () => _openImage( + context: context, + initialImageIndex: position, + ), + child: Column( + children: [ + Stack( + children: [ + AspectRatio( + aspectRatio: 1.0, + child: SmoothImage( + rounded: false, + imageProvider: transientFile.getImageProvider(), + ), ), - ], - ), - Expanded( - child: Center( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - imageField - .getProductImageTitle(AppLocalizations.of(context)), - style: Theme.of(context).textTheme.headlineMedium, - textAlign: TextAlign.center, + if (transientFile.isImageAvailable() && + !transientFile.isServerImage()) + const Center( + child: CloudUploadAnimation.circle(size: 30.0), + ), + if (expired) + Positioned.directional( + textDirection: Directionality.of(context), + bottom: VERY_SMALL_SPACE, + end: VERY_SMALL_SPACE, + child: const icons.Outdated( + color: Colors.black87, + shadow: Shadow( + color: Colors.white38, + blurRadius: 2.0, + ), + ), + ), + ], + ), + Expanded( + child: Center( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + label, + style: Theme.of(context).textTheme.headlineMedium, + textAlign: TextAlign.center, + ), ), ), ), - ), - ], + ], + ), ), ), ); @@ -261,9 +285,9 @@ class _PhotoRow extends StatelessWidget { TransientFile _getTransientFile( final ImageField imageField, ) => - TransientFile.fromProductImageData( - getProductImageData(product, imageField, language), - product.barcode!, + TransientFile.fromProduct( + product, + imageField, language, ); From 71ccd1f3e44601fe0a1f69682315280bd67e212e Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 23 Jul 2024 09:53:54 +0200 Subject: [PATCH 77/85] Migrate actions to Java 17 (#5500) --- .github/workflows/postsubmit.yml | 2 +- .github/workflows/waldo_sessions.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/postsubmit.yml b/.github/workflows/postsubmit.yml index 6c1dced4743..3ba797c1cda 100644 --- a/.github/workflows/postsubmit.yml +++ b/.github/workflows/postsubmit.yml @@ -19,7 +19,7 @@ jobs: uses: actions/setup-java@v4.2.1 with: distribution: 'zulu' - java-version: 11 + java-version: 17 # Get the flutter version from ./flutter-version.txt - run: echo "FLUTTER_VERSION=$(cat flutter-version.txt)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/waldo_sessions.yml b/.github/workflows/waldo_sessions.yml index 0a0a7cadb07..d6765be39df 100644 --- a/.github/workflows/waldo_sessions.yml +++ b/.github/workflows/waldo_sessions.yml @@ -30,7 +30,7 @@ jobs: uses: actions/setup-java@v4.2.1 with: distribution: 'zulu' - java-version: 11 + java-version: 17 # Get the flutter version from ./flutter-version.txt - run: echo "FLUTTER_VERSION=$(cat flutter-version.txt)" >> $GITHUB_OUTPUT From 9cbcf75d5ddc27e4237fb7cf44dc008c2c85ed42 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 23 Jul 2024 09:54:25 +0200 Subject: [PATCH 78/85] feat: Disallow emojis on brand name (#5461) * Disallow emojis on brand name * Fix Lint warning --- .../lib/generic_lib/widgets/smooth_text_form_field.dart | 8 ++++++++ packages/smooth_app/lib/helpers/strings_helper.dart | 4 ++++ .../lib/pages/input/smooth_autocomplete_text_field.dart | 8 ++++++++ .../lib/pages/product/add_basic_details_page.dart | 1 + 4 files changed, 21 insertions(+) diff --git a/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart b/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart index ce4d0fc6166..0c2acb0bb9e 100644 --- a/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart +++ b/packages/smooth_app/lib/generic_lib/widgets/smooth_text_form_field.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/helpers/strings_helper.dart'; enum TextFieldTypes { PLAIN_TEXT, @@ -25,6 +27,7 @@ class SmoothTextFormField extends StatefulWidget { this.autofocus, this.focusNode, this.spellCheckConfiguration, + this.allowEmojis = true, }); final TextFieldTypes type; @@ -42,6 +45,7 @@ class SmoothTextFormField extends StatefulWidget { final bool? autofocus; final FocusNode? focusNode; final SpellCheckConfiguration? spellCheckConfiguration; + final bool allowEmojis; @override State createState() => _SmoothTextFormFieldState(); @@ -90,6 +94,10 @@ class _SmoothTextFormFieldState extends State { onFieldSubmitted: widget.onFieldSubmitted, style: TextStyle(fontSize: textSize), cursorHeight: textSize * (textStyle.height ?? 1.4), + inputFormatters: [ + if (!widget.allowEmojis) + FilteringTextInputFormatter.deny(TextHelper.emojiRegex), + ], decoration: InputDecoration( contentPadding: const EdgeInsets.symmetric( horizontal: LARGE_SPACE, diff --git a/packages/smooth_app/lib/helpers/strings_helper.dart b/packages/smooth_app/lib/helpers/strings_helper.dart index 055db2cb4db..2d84a6827e8 100644 --- a/packages/smooth_app/lib/helpers/strings_helper.dart +++ b/packages/smooth_app/lib/helpers/strings_helper.dart @@ -48,6 +48,10 @@ extension StringExtensions on String { class TextHelper { const TextHelper._(); + /// From [https://github.com/duocnguyen6799/remove_emoji_input_formatter/blob/main/lib/src/constant.dart] + static final RegExp emojiRegex = RegExp( + '/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?|\u200D(?:\uD83D\uDC8B\u200D)?)\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69])|\uD83E\uDEF1\uD83C\uDFFF\u200D\uD83E\uDEF2)(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?|\u200D(?:\uD83D\uDC8B\u200D)?)\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69])|\uD83E\uDEF1\uD83C\uDFFE\u200D\uD83E\uDEF2)(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?|\u200D(?:\uD83D\uDC8B\u200D)?)\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69])|\uD83E\uDEF1\uD83C\uDFFD\u200D\uD83E\uDEF2)(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?|\u200D(?:\uD83D\uDC8B\u200D)?)\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69])|\uD83E\uDEF1\uD83C\uDFFC\u200D\uD83E\uDEF2)(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?|\u200D(?:\uD83D\uDC8B\u200D)?)\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69])|\uD83E\uDEF1\uD83C\uDFFB\u200D\uD83E\uDEF2)(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|[\u2695\u2696\u2708]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])))|\u200D(?:\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?|\u200D(?:\uD83D\uDC8B\u200D)?)\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\u200D[\u2695\u2696\u2708])?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764(?:\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F?\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F?\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3C-\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83D\uDC41\uFE0F?\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83C\uDFF3\uFE0F?\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F?\u200D\u26A7|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDEF1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764(?:\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\u200D(?:\uD83D\uDD25|\uD83E\uDE79))|\uD83D\uDC41\uFE0F?|\uD83C\uDFF3\uFE0F?|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3C-\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#*0-9]\uFE0F?\u20E3|\uD83E\uDD3C(?:\uD83C[\uDFFB-\uDFFF])|\u2764\uFE0F?|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF6])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD3C\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF6]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDDDE\uDDDF]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\uD83C[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDD-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7C\uDE80-\uDE86\uDE90-\uDEAC\uDEB0-\uDEBA\uDEC0-\uDEC2\uDED0-\uDED9\uDEE0-\uDEE7]'); + /// Split the text into parts. /// Eg: with the symbol '*' /// 'Hello *world*!' => [('Hello ', defaultStyle), ('world', highlightedStyle), ('!', defaultStyle)] diff --git a/packages/smooth_app/lib/pages/input/smooth_autocomplete_text_field.dart b/packages/smooth_app/lib/pages/input/smooth_autocomplete_text_field.dart index 251643e6c2c..478bd00201f 100644 --- a/packages/smooth_app/lib/pages/input/smooth_autocomplete_text_field.dart +++ b/packages/smooth_app/lib/pages/input/smooth_autocomplete_text_field.dart @@ -2,8 +2,10 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:smooth_app/generic_lib/design_constants.dart'; +import 'package:smooth_app/helpers/strings_helper.dart'; import 'package:smooth_app/pages/product/autocomplete.dart'; /// Autocomplete text field. @@ -16,6 +18,7 @@ class SmoothAutocompleteTextField extends StatefulWidget { required this.constraints, required this.manager, this.minLengthForSuggestions = 1, + this.allowEmojis = true, }); final FocusNode focusNode; @@ -25,6 +28,7 @@ class SmoothAutocompleteTextField extends StatefulWidget { final BoxConstraints constraints; final int minLengthForSuggestions; final AutocompleteManager? manager; + final bool allowEmojis; @override State createState() => @@ -73,6 +77,10 @@ class _SmoothAutocompleteTextFieldState TextField( controller: widget.controller, onChanged: (_) => setState(() => _selectedSearch = null), + inputFormatters: [ + if (!widget.allowEmojis) + FilteringTextInputFormatter.deny(TextHelper.emojiRegex), + ], decoration: InputDecoration( filled: true, border: const OutlineInputBorder( diff --git a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart index c59d5fdd03d..75480b7b753 100644 --- a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart +++ b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart @@ -194,6 +194,7 @@ class _AddBasicDetailsPageState extends State { focusNode: _focusNode, controller: _brandNameController, autocompleteKey: _autocompleteKey, + allowEmojis: false, hintText: appLocalizations.brand_name, constraints: constraints, manager: AutocompleteManager( From fe0313910b2149fd1e9e323929ca0c1bc5a90a64 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 23 Jul 2024 09:54:45 +0200 Subject: [PATCH 79/85] chore: Upgrade dependencies (#5490) * Upgrade dependencies * Downgrade audioplayers * Remove Lint warning * Bring back pupspec.lock * Also bring devtools_options.yaml --- packages/app_store/uri_store/pubspec.yaml | 2 +- packages/smooth_app/devtools_options.yaml | 3 + .../smooth_app/lib/query/product_query.dart | 2 +- packages/smooth_app/pubspec.lock | 112 +++++++++--------- packages/smooth_app/pubspec.yaml | 22 ++-- 5 files changed, 72 insertions(+), 69 deletions(-) create mode 100644 packages/smooth_app/devtools_options.yaml diff --git a/packages/app_store/uri_store/pubspec.yaml b/packages/app_store/uri_store/pubspec.yaml index 1e661bdb92a..ef0e35cefff 100644 --- a/packages/app_store/uri_store/pubspec.yaml +++ b/packages/app_store/uri_store/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: app_store_shared: path: ../shared - url_launcher: 6.1.3 + url_launcher: 6.3.0 dev_dependencies: flutter_test: diff --git a/packages/smooth_app/devtools_options.yaml b/packages/smooth_app/devtools_options.yaml new file mode 100644 index 00000000000..fa0b357c4f4 --- /dev/null +++ b/packages/smooth_app/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/packages/smooth_app/lib/query/product_query.dart b/packages/smooth_app/lib/query/product_query.dart index 49bc51770d4..4f636f519bd 100644 --- a/packages/smooth_app/lib/query/product_query.dart +++ b/packages/smooth_app/lib/query/product_query.dart @@ -145,7 +145,7 @@ abstract class ProductQuery { } OpenFoodAPIConfiguration.uuid = uuid; await Sentry.configureScope((Scope scope) { - scope.setExtra('uuid', OpenFoodAPIConfiguration.uuid); + scope.contexts['uuid'] = OpenFoodAPIConfiguration.uuid; scope.setUser(SentryUser(username: OpenFoodAPIConfiguration.uuid)); }); } diff --git a/packages/smooth_app/pubspec.lock b/packages/smooth_app/pubspec.lock index 4eb4e3e3ea6..31d9c599402 100644 --- a/packages/smooth_app/pubspec.lock +++ b/packages/smooth_app/pubspec.lock @@ -209,34 +209,34 @@ packages: dependency: transitive description: name: camera_android - sha256: b350ac087f111467e705b2b76cc1322f7f5bdc122aa83b4b243b0872f390d229 + sha256: eacc70b6c81fa5e17921302fc17a1ae5983d94ce1d76c71e4869abdc615d35d2 url: "https://pub.dev" source: hosted - version: "0.10.9+2" + version: "0.10.9+8" camera_avfoundation: dependency: transitive description: name: camera_avfoundation - sha256: "7d021e8cd30d9b71b8b92b4ad669e80af432d722d18d6aac338572754a786c15" + sha256: b5093a82537b64bb88d4244f8e00b5ba69e822a5994f47b31d11400e1db975e5 url: "https://pub.dev" source: hosted - version: "0.9.16" + version: "0.9.17+1" camera_platform_interface: dependency: transitive description: name: camera_platform_interface - sha256: a250314a48ea337b35909a4c9d5416a208d736dcb01d0b02c6af122be66660b0 + sha256: b3ede1f171532e0d83111fe0980b46d17f1aa9788a07a2fbed07366bbdbb9061 url: "https://pub.dev" source: hosted - version: "2.7.4" + version: "2.8.0" camera_web: dependency: transitive description: name: camera_web - sha256: "9e9aba2fbab77ce2472924196ff8ac4dd8f9126c4f9a3096171cd1d870d6b26c" + sha256: b9235ec0a2ce949daec546f1f3d86f05c3921ed31c7d9ab6b7c03214d152fc2d url: "https://pub.dev" source: hosted - version: "0.3.3" + version: "0.3.4" carousel_slider: dependency: "direct main" description: @@ -417,10 +417,10 @@ packages: dependency: "direct main" description: name: email_validator - sha256: e9a90f27ab2b915a27d7f9c2a7ddda5dd752d6942616ee83529b686fc086221b + sha256: b19aa5d92fdd76fbc65112060c94d45ba855105a28bb6e462de7ff03b12fa1fb url: "https://pub.dev" source: hosted - version: "2.1.17" + version: "3.0.0" fake_async: dependency: transitive description: @@ -571,10 +571,10 @@ packages: dependency: "direct main" description: name: flutter_image_compress - sha256: "4edadb0ca2f957b85190e9c3aa728569b91b64b6e06e0eec5b622d47a8692ab2" + sha256: "45a3071868092a61b11044c70422b04d39d4d9f2ef536f3c5b11fb65a1e7dd90" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" flutter_image_compress_common: dependency: transitive description: @@ -648,18 +648,18 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0 + sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e url: "https://pub.dev" source: hosted - version: "2.0.19" + version: "2.0.20" flutter_secure_storage: dependency: "direct main" description: @@ -730,10 +730,10 @@ packages: dependency: "direct main" description: name: flutter_widget_from_html_core - sha256: e8f4f8b461a140ffb7c71f938bc76efc758893e7468843d9dbf70cb0b9e900cb + sha256: "23c72f8ce7ba1fd6f8fbdc107f07e04fe152ffd587be1b012938904bfda31950" url: "https://pub.dev" source: hosted - version: "0.8.5+3" + version: "0.8.3+1" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -767,18 +767,18 @@ packages: dependency: "direct main" description: name: go_router - sha256: c247a4f76071c3b97bb5ae8912968870d5565644801c5e09f3bc961b4d874895 + sha256: "39dd52168d6c59984454183148dc3a5776960c61083adfc708cc79a7b3ce1ba8" url: "https://pub.dev" source: hosted - version: "12.1.1" + version: "14.2.1" graphs: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" hive: dependency: "direct main" description: @@ -823,26 +823,26 @@ packages: dependency: "direct main" description: name: image - sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" url: "https://pub.dev" source: hosted - version: "4.1.7" + version: "4.2.0" image_picker: dependency: "direct main" description: name: image_picker - sha256: "33974eca2e87e8b4e3727f1b94fa3abcb25afe80b6bc2c4d449a0e150aedf720" + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: "0f57fee1e8bfadf8cc41818bbcd7f72e53bb768a54d9496355d5e8a5681a19f1" + sha256: cea2bd5b9fcff039a4901d3b13c67fe747f940be9ba76bde1bcd218d168eeb7f url: "https://pub.dev" source: hosted - version: "0.8.12+1" + version: "0.8.12+6" image_picker_for_web: dependency: transitive description: @@ -996,10 +996,10 @@ packages: dependency: transitive description: name: logger - sha256: af05cc8714f356fd1f3888fb6741cbe9fbe25cdb6eedbab80e1a6db21047d4a4 + sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" logging: dependency: transitive description: @@ -1157,10 +1157,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d + sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.7" path_provider_foundation: dependency: transitive description: @@ -1189,10 +1189,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" permission_handler: dependency: "direct main" description: @@ -1317,10 +1317,10 @@ packages: dependency: transitive description: name: qr - sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" qr_code_scanner: dependency: transitive description: @@ -1370,18 +1370,18 @@ packages: dependency: transitive description: name: sentry - sha256: "7342ef4c18932881730ac941a07a6e4cf76fe99cd1ea3bef06e53a6a1402dec0" + sha256: cbc29cbdd8a047aab3df42f826daf07e58dfb2e1d550895d1021a6d4e618b00d url: "https://pub.dev" source: hosted - version: "8.3.0" + version: "8.4.0" sentry_flutter: dependency: "direct main" description: name: sentry_flutter - sha256: "475cf49682e4d1eb48caa2577502721bcfdcbb63f215de57b3b246d52f4f7914" + sha256: "96ce085e1be6c9963d93d42d6ba5c67484c076c59d25c94a7ba906549dc6c635" url: "https://pub.dev" source: hosted - version: "8.3.0" + version: "8.4.0" share_plus: dependency: "direct main" description: @@ -1410,10 +1410,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" + sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_foundation: dependency: transitive description: @@ -1434,10 +1434,10 @@ packages: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + sha256: "034650b71e73629ca08a0bd789fd1d83cc63c2d1e405946f7cef7bc37432f93a" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" shared_preferences_web: dependency: transitive description: @@ -1615,26 +1615,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: f118f30f4301453d155c236a17d9ba53ec02a342591290aff91ae0fda4dc5428 + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" url: "https://pub.dev" source: hosted - version: "6.1.3" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" + sha256: "95d8027db36a0e52caf55680f91e33ea6aa12a3ce608c90b06f4e429a21067ac" url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.5" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_linux: dependency: transitive description: @@ -1759,10 +1759,10 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932" + sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.0" webview_flutter_android: dependency: "direct main" description: @@ -1783,18 +1783,18 @@ packages: dependency: "direct main" description: name: webview_flutter_wkwebview - sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7 + sha256: "9c62cc46fa4f2d41e10ab81014c1de470a6c6f26051a2de32111b2ee55287feb" url: "https://pub.dev" source: hosted - version: "3.13.0" + version: "3.14.0" win32: dependency: transitive description: name: win32 - sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "5.5.1" win32_registry: dependency: transitive description: diff --git a/packages/smooth_app/pubspec.yaml b/packages/smooth_app/pubspec.yaml index f0619116fbd..affe85f10e5 100644 --- a/packages/smooth_app/pubspec.yaml +++ b/packages/smooth_app/pubspec.yaml @@ -13,21 +13,21 @@ dependencies: sdk: flutter async: 2.11.0 - go_router: 12.1.1 + go_router: 14.2.1 barcode_widget: 2.0.4 carousel_slider: 4.2.1 cupertino_icons: 1.0.8 flutter_svg: 2.0.10+1 flutter_map: 6.1.0 html: 0.15.4 - flutter_widget_from_html_core: 0.8.5+3 + flutter_widget_from_html_core: 0.8.3+1 fwfh_selectable_text: 0.8.3+1 flutter_secure_storage: 9.2.2 hive: 2.2.3 hive_flutter: 1.1.0 http: 1.2.0 http_parser: 4.0.2 - image_picker: 1.1.1 + image_picker: 1.1.2 iso_countries: 2.2.0 latlong2: 0.9.1 matomo_tracker: 4.1.1 @@ -37,10 +37,10 @@ dependencies: photo_view: 0.15.0 uuid: 3.0.7 provider: 6.1.2 - sentry_flutter: 8.3.0 + sentry_flutter: 8.4.0 sqflite: 2.3.3+1 sqflite_common_ffi: 2.3.3 - url_launcher: 6.1.3 + url_launcher: 6.3.0 visibility_detector: 0.4.0+2 app_settings: 5.1.1 diacritic: 0.1.5 @@ -48,8 +48,8 @@ dependencies: path: ../app_store/shared audioplayers: 5.2.1 flutter_email_sender: 6.0.3 - flutter_native_splash: 2.4.0 - image: 4.1.7 + flutter_native_splash: 2.4.1 + image: 4.2.0 auto_size_text: 3.0.0 crop_image: 1.0.13 shared_preferences: 2.2.3 @@ -61,16 +61,16 @@ dependencies: fimber: 0.7.0 shimmer: ^3.0.0 rive: 0.13.4 - webview_flutter: 4.7.0 + webview_flutter: 4.8.0 webview_flutter_android: 3.16.4 - webview_flutter_wkwebview: 3.13.0 + webview_flutter_wkwebview: 3.14.0 flutter_custom_tabs: 2.1.0 - flutter_image_compress: 2.2.0 + flutter_image_compress: 2.3.0 connectivity_plus: 5.0.2 dart_ping: 9.0.1 dart_ping_ios: 4.0.2 flutter_animation_progress_bar: 2.3.1 - email_validator: 2.1.17 + email_validator: 3.0.0 sliver_tools: 0.2.12 # According to the build variant, only one "app store" implementation must be added when building a release From 4404eb6b45d816768f41310ff6c8dc6cba847f68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:40:44 +0200 Subject: [PATCH 80/85] chore(deps): bump crowdin/github-action from 2.0.0 to 2.1.0 (#5508) Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 2.0.0 to 2.1.0. - [Release notes](https://github.com/crowdin/github-action/releases) - [Commits](https://github.com/crowdin/github-action/compare/v2.0.0...v2.1.0) --- updated-dependencies: - dependency-name: crowdin/github-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 8718d5b05ea..ba53a02f798 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v4 - name: crowdin action - uses: crowdin/github-action@v2.0.0 + uses: crowdin/github-action@v2.1.0 continue-on-error: true with: # Upload sources to Crowdin From cc3756df59ebb895a1ceaee001b7f51e7fb25133 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Jul 2024 18:40:14 +0200 Subject: [PATCH 81/85] chore(deps): bump crowdin/github-action from 2.1.0 to 2.1.1 (#5513) Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/crowdin/github-action/releases) - [Commits](https://github.com/crowdin/github-action/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: crowdin/github-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index ba53a02f798..4393100fc57 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v4 - name: crowdin action - uses: crowdin/github-action@v2.1.0 + uses: crowdin/github-action@v2.1.1 continue-on-error: true with: # Upload sources to Crowdin From 9ad38875771ee301cea14ad5a12353716bb843c3 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 30 Jul 2024 08:54:05 +0200 Subject: [PATCH 82/85] An attempt to fix the blank external page (#5514) --- .../lib/pages/navigator/external_page.dart | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/smooth_app/lib/pages/navigator/external_page.dart b/packages/smooth_app/lib/pages/navigator/external_page.dart index 4c5cef2ce6c..d28bd9bb2b0 100644 --- a/packages/smooth_app/lib/pages/navigator/external_page.dart +++ b/packages/smooth_app/lib/pages/navigator/external_page.dart @@ -8,6 +8,7 @@ import 'package:path/path.dart' as path; import 'package:smooth_app/helpers/launch_url_helper.dart'; import 'package:smooth_app/pages/navigator/app_navigator.dart'; import 'package:smooth_app/query/product_query.dart'; +import 'package:smooth_app/services/smooth_services.dart'; /// This screen is only used for deep links! /// @@ -58,19 +59,24 @@ class _ExternalPageState extends State { url = '$url?lc=${language.offTag}'; } - if (Platform.isAndroid) { - await tabs.launchUrl( - Uri.parse(url), - customTabsOptions: const tabs.CustomTabsOptions( - showTitle: true, - ), - ); - } else { - await LaunchUrlHelper.launchURL(url); - } - - if (mounted) { - AppNavigator.of(context).pop(); + try { + if (Platform.isAndroid) { + WidgetsFlutterBinding.ensureInitialized(); + await tabs.launchUrl( + Uri.parse(url), + customTabsOptions: const tabs.CustomTabsOptions( + showTitle: true, + ), + ); + } else { + await LaunchUrlHelper.launchURL(url); + } + } catch (e) { + Logs.e('Unable to open an external link', ex: e); + } finally { + if (mounted) { + AppNavigator.of(context).pop(); + } } }); } From ddb127d4cd9f08b852cc4746f9d98782d244bc58 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Tue, 30 Jul 2024 08:54:18 +0200 Subject: [PATCH 83/85] Remove flutter map attribution (#5511) --- .../knowledge_panels/knowledge_panel_world_map_card.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_world_map_card.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_world_map_card.dart index 28e15cfebf3..a352587fd53 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_world_map_card.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_world_map_card.dart @@ -71,6 +71,7 @@ class KnowledgePanelWorldMapCard extends StatelessWidget { RichAttributionWidget( popupInitialDisplayDuration: const Duration(seconds: 5), animationConfig: const ScaleRAWA(), + showFlutterMapAttribution: false, attributions: [ TextSourceAttribution( 'OpenStreetMap contributors', From a1274f96a84884fa315837e64db8d2b8118403c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 08:54:58 +0200 Subject: [PATCH 84/85] chore(deps): bump fastlane in /packages/smooth_app/android (#5516) Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.221.1 to 2.222.0. - [Release notes](https://github.com/fastlane/fastlane/releases) - [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md) - [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.221.1...fastlane/2.222.0) --- updated-dependencies: - dependency-name: fastlane dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/android/Gemfile.lock | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/smooth_app/android/Gemfile.lock b/packages/smooth_app/android/Gemfile.lock index c2fcdce8648..cd96c783d17 100644 --- a/packages/smooth_app/android/Gemfile.lock +++ b/packages/smooth_app/android/Gemfile.lock @@ -11,25 +11,25 @@ GEM base64 nkf rexml - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.945.0) - aws-sdk-core (3.197.1) + aws-partitions (1.958.0) + aws-sdk-core (3.201.3) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.85.0) - aws-sdk-core (~> 3, >= 3.197.0) - aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.152.3) - aws-sdk-core (~> 3, >= 3.197.0) + aws-sdk-kms (1.88.0) + aws-sdk-core (~> 3, >= 3.201.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.156.0) + aws-sdk-core (~> 3, >= 3.201.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.8) - aws-sigv4 (1.8.0) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.9.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -44,7 +44,7 @@ GEM domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.110.0) + excon (0.111.0) faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -66,7 +66,7 @@ GEM faraday-httpclient (1.0.1) faraday-multipart (1.0.4) multipart-post (~> 2) - faraday-net_http (1.0.1) + faraday-net_http (1.0.2) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) @@ -74,7 +74,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.221.1) + fastlane (2.222.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -162,7 +162,7 @@ GEM json (2.7.2) jwt (2.8.2) base64 - mini_magick (4.13.1) + mini_magick (4.13.2) mini_mime (1.1.5) multi_json (1.15.0) multipart-post (2.4.1) @@ -172,7 +172,7 @@ GEM optparse (0.5.0) os (1.1.4) plist (3.7.1) - public_suffix (5.1.1) + public_suffix (6.0.1) rake (13.2.1) representable (3.2.0) declarative (< 0.1.0) From 41be2eca5e5f532d288e7321fbb4603b25560201 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 08:55:21 +0200 Subject: [PATCH 85/85] chore(deps): bump fastlane in /packages/smooth_app/ios (#5515) Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.221.1 to 2.222.0. - [Release notes](https://github.com/fastlane/fastlane/releases) - [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md) - [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.221.1...fastlane/2.222.0) --- updated-dependencies: - dependency-name: fastlane dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/smooth_app/ios/Gemfile.lock | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/smooth_app/ios/Gemfile.lock b/packages/smooth_app/ios/Gemfile.lock index 6c82f499c3b..ac033ddb6f3 100644 --- a/packages/smooth_app/ios/Gemfile.lock +++ b/packages/smooth_app/ios/Gemfile.lock @@ -11,25 +11,25 @@ GEM base64 nkf rexml - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.945.0) - aws-sdk-core (3.197.1) + aws-partitions (1.958.0) + aws-sdk-core (3.201.3) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.85.0) - aws-sdk-core (~> 3, >= 3.197.0) - aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.152.3) - aws-sdk-core (~> 3, >= 3.197.0) + aws-sdk-kms (1.88.0) + aws-sdk-core (~> 3, >= 3.201.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.156.0) + aws-sdk-core (~> 3, >= 3.201.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.8) - aws-sigv4 (1.8.0) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.9.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -45,7 +45,7 @@ GEM domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.110.0) + excon (0.111.0) faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -67,7 +67,7 @@ GEM faraday-httpclient (1.0.1) faraday-multipart (1.0.4) multipart-post (~> 2) - faraday-net_http (1.0.1) + faraday-net_http (1.0.2) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) @@ -75,7 +75,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.221.1) + fastlane (2.222.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -163,7 +163,7 @@ GEM json (2.7.2) jwt (2.8.2) base64 - mini_magick (4.13.1) + mini_magick (4.13.2) mini_mime (1.1.5) multi_json (1.15.0) multipart-post (2.4.1) @@ -173,7 +173,7 @@ GEM optparse (0.5.0) os (1.1.4) plist (3.7.1) - public_suffix (5.1.1) + public_suffix (6.0.1) rake (13.2.1) representable (3.2.0) declarative (< 0.1.0)