From 8e9cc2b53aeefc2f161392d91efac54b790779d7 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Sun, 30 Jul 2023 12:13:39 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20Localized=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/l10n.yaml | 8 + example/lib/extensions/l10n_extensions.dart | 11 + example/lib/l10n/app_en.arb | 36 ++ example/lib/l10n/app_zh.arb | 36 ++ example/lib/l10n/gen/app_localizations.dart | 325 ++++++++++++++++++ .../lib/l10n/gen/app_localizations_en.dart | 109 ++++++ .../gen/app_localizations_untranslated.json | 1 + .../lib/l10n/gen/app_localizations_zh.dart | 109 ++++++ example/lib/main.dart | 22 +- example/lib/models/picker_method.dart | 72 ++-- example/lib/pages/home_page.dart | 21 +- example/lib/widgets/selected_assets_view.dart | 3 +- 12 files changed, 698 insertions(+), 55 deletions(-) create mode 100644 example/l10n.yaml create mode 100644 example/lib/extensions/l10n_extensions.dart create mode 100644 example/lib/l10n/app_en.arb create mode 100644 example/lib/l10n/app_zh.arb create mode 100644 example/lib/l10n/gen/app_localizations.dart create mode 100644 example/lib/l10n/gen/app_localizations_en.dart create mode 100644 example/lib/l10n/gen/app_localizations_untranslated.json create mode 100644 example/lib/l10n/gen/app_localizations_zh.dart diff --git a/example/l10n.yaml b/example/l10n.yaml new file mode 100644 index 0000000..b99f4e2 --- /dev/null +++ b/example/l10n.yaml @@ -0,0 +1,8 @@ +arb-dir: lib/l10n +# format: true +output-class: AppLocalizations +output-dir: lib/l10n/gen +output-localization-file: app_localizations.dart +template-arb-file: app_en.arb +synthetic-package: false +untranslated-messages-file: lib/l10n/gen/app_localizations_untranslated.json diff --git a/example/lib/extensions/l10n_extensions.dart b/example/lib/extensions/l10n_extensions.dart new file mode 100644 index 0000000..97c3922 --- /dev/null +++ b/example/lib/extensions/l10n_extensions.dart @@ -0,0 +1,11 @@ +// Copyright 2019 The FlutterCandies author. All rights reserved. +// Use of this source code is governed by an Apache license that can be found +// in the LICENSE file. + +import 'package:flutter/widgets.dart'; + +import '../l10n/gen/app_localizations.dart'; + +extension BuildContextExtension on BuildContext { + AppLocalizations get l10n => AppLocalizations.of(this)!; +} diff --git a/example/lib/l10n/app_en.arb b/example/lib/l10n/app_en.arb new file mode 100644 index 0000000..eb18e5e --- /dev/null +++ b/example/lib/l10n/app_en.arb @@ -0,0 +1,36 @@ +{ + "@@locale": "en", + "appTitle": "WeChat Camera Picker Demo", + "appVersion": "Version: {version}", + "appVersionUnknown": "unknown", + "selectedAssetsText": "Selected Assets", + "pickMethodNotice": "Pickers in this page are located at the {dist}, defined by `pickMethods`.", + "pickMethodPhotosName": "Taking photos", + "pickMethodPhotosDescription": "Use cameras only to take photos.", + "pickMethodPhotosAndVideosName": "Taking photos and videos", + "pickMethodPhotosAndVideosDescription": "Use cameras to take photos and videos.", + "pickMethodVideosName": "Taking videos", + "pickMethodVideosDescription": "Use cameras only to take videos.", + "pickMethodVideosByTapName": "Taking videos by tap", + "pickMethodVideosByTapDescription": "Use cameras only to take videos, but not with long-press, just a single tap.", + "pickMethodSilenceRecordingName": "Silence recording", + "pickMethodSilenceRecordingDescription": "Make recordings silent.", + "pickMethodAutoPreviewVideosName": "Auto preview videos", + "pickMethodAutoPreviewVideosDescription": "Play videos automatically in the preview after captured.", + "pickMethodNoDurationLimitName": "No duration limit", + "pickMethodNoDurationLimitDescription": "Record as long as you with (if your device stays alive)...", + "pickMethodCustomizableThemeName": "Customizable theme (ThemeData)", + "pickMethodCustomizableThemeDescription": "Picking assets with the light theme or with a different color.", + "pickMethodRotateInTurnsName": "Rotate picker in turns", + "pickMethodRotateInTurnsDescription": "Rotate the picker layout in quarter turns, without the camera preview.", + "pickMethodPreventScalingName": "Prevent scaling for camera preview", + "pickMethodPreventScalingDescription": "Camera preview will not be scaled to cover the whole screen of the device, only fit for the raw aspect ratio.", + "pickMethodLowerResolutionName": "Lower resolutions", + "pickMethodLowerResolutionDescription": "Use a lower resolution preset might be helpful in some specific scenarios.", + "pickMethodPreferFrontCameraName": "Prefer front camera", + "pickMethodPreferFrontCameraDescription": "Use the front camera as the preferred lens direction if the device supports.", + "pickMethodPreferFlashlightOnName": "Prefer flashlight always on", + "pickMethodPreferFlashlightOnDescription": "Prefer to keep using the flashlight during captures.", + "pickMethodForegroundBuilderName": "Foreground builder", + "pickMethodForegroundBuilderDescription": "Build your widgets with the given CameraController on the top of the camera preview." +} \ No newline at end of file diff --git a/example/lib/l10n/app_zh.arb b/example/lib/l10n/app_zh.arb new file mode 100644 index 0000000..a6506c3 --- /dev/null +++ b/example/lib/l10n/app_zh.arb @@ -0,0 +1,36 @@ +{ + "@@locale": "zh", + "appTitle": "WeChat Camera Picker 示例", + "appVersion": "版本:{version}", + "appVersionUnknown": "未知", + "selectedAssetsText": "已选的资源", + "pickMethodNotice": "该页面的所有选择器的代码位于 {dist},由 `pickMethods` 定义。", + "pickMethodPhotosName": "拍照", + "pickMethodPhotosDescription": "使用相机拍照。", + "pickMethodPhotosAndVideosName": "拍照和录像", + "pickMethodPhotosAndVideosDescription": "使用相机进行拍照和录像。", + "pickMethodVideosName": "录像", + "pickMethodVideosDescription": "使用相机录像。", + "pickMethodVideosByTapName": "轻触录像", + "pickMethodVideosByTapDescription": "轻触录像按钮进行录像,而不是长按。", + "pickMethodSilenceRecordingName": "静音录像", + "pickMethodSilenceRecordingDescription": "录像时不录制声音。", + "pickMethodAutoPreviewVideosName": "自动预览录制的视频", + "pickMethodAutoPreviewVideosDescription": "预览录制的视频时,自动播放。", + "pickMethodNoDurationLimitName": "无时长限制录像", + "pickMethodNoDurationLimitDescription": "想录多久,就录多久(只要手机健在)。", + "pickMethodCustomizableThemeName": "自定义主题 (ThemeData)", + "pickMethodCustomizableThemeDescription": "可以用亮色或其他颜色及自定义的主题进行选择。", + "pickMethodRotateInTurnsName": "旋转选择器的布局", + "pickMethodRotateInTurnsDescription": "顺时针旋转选择器的元素布局,不旋转相机视图。", + "pickMethodPreventScalingName": "禁止缩放相机预览", + "pickMethodPreventScalingDescription": "相机预览视图不会被放大到覆盖整个屏幕,仅适应原始的预览比例。", + "pickMethodLowerResolutionName": "低分辨率拍照", + "pickMethodLowerResolutionDescription": "某些情况或机型使用低分辨率拍照会有稳定性改善。", + "pickMethodPreferFrontCameraName": "首选前置摄像头", + "pickMethodPreferFrontCameraDescription": "在设备支持时首选使用前置摄像头。", + "pickMethodPreferFlashlightOnName": "首选闪光灯始终启用", + "pickMethodPreferFlashlightOnDescription": "在设备支持时首选闪光灯始终启用。", + "pickMethodForegroundBuilderName": "构建前景", + "pickMethodForegroundBuilderDescription": "通过 CameraController 构建在相机预览部分的前景 widget。" +} \ No newline at end of file diff --git a/example/lib/l10n/gen/app_localizations.dart b/example/lib/l10n/gen/app_localizations.dart new file mode 100644 index 0000000..16613e5 --- /dev/null +++ b/example/lib/l10n/gen/app_localizations.dart @@ -0,0 +1,325 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart' as intl; + +import 'app_localizations_en.dart'; +import 'app_localizations_zh.dart'; + +/// Callers can lookup localized strings with an instance of AppLocalizations +/// returned by `AppLocalizations.of(context)`. +/// +/// Applications need to include `AppLocalizations.delegate()` in their app's +/// `localizationDelegates` list, and the locales they support in the app's +/// `supportedLocales` list. For example: +/// +/// ```dart +/// import 'gen/app_localizations.dart'; +/// +/// return MaterialApp( +/// localizationsDelegates: AppLocalizations.localizationsDelegates, +/// supportedLocales: AppLocalizations.supportedLocales, +/// home: MyApplicationHome(), +/// ); +/// ``` +/// +/// ## Update pubspec.yaml +/// +/// Please make sure to update your pubspec.yaml to include the following +/// packages: +/// +/// ```yaml +/// dependencies: +/// # Internationalization support. +/// flutter_localizations: +/// sdk: flutter +/// intl: any # Use the pinned version from flutter_localizations +/// +/// # Rest of dependencies +/// ``` +/// +/// ## iOS Applications +/// +/// iOS applications define key application metadata, including supported +/// locales, in an Info.plist file that is built into the application bundle. +/// To configure the locales supported by your app, you’ll need to edit this +/// file. +/// +/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. +/// Then, in the Project Navigator, open the Info.plist file under the Runner +/// project’s Runner folder. +/// +/// Next, select the Information Property List item, select Add Item from the +/// Editor menu, then select Localizations from the pop-up menu. +/// +/// Select and expand the newly-created Localizations item then, for each +/// locale your application supports, add a new item and select the locale +/// you wish to add from the pop-up menu in the Value field. This list should +/// be consistent with the languages listed in the AppLocalizations.supportedLocales +/// property. +abstract class AppLocalizations { + AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + + final String localeName; + + static AppLocalizations? of(BuildContext context) { + return Localizations.of(context, AppLocalizations); + } + + static const LocalizationsDelegate delegate = _AppLocalizationsDelegate(); + + /// A list of this localizations delegate along with the default localizations + /// delegates. + /// + /// Returns a list of localizations delegates containing this delegate along with + /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, + /// and GlobalWidgetsLocalizations.delegate. + /// + /// Additional delegates can be added by appending to this list in + /// MaterialApp. This list does not have to be used at all if a custom list + /// of delegates is preferred or required. + static const List> localizationsDelegates = >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; + + /// A list of this localizations delegate's supported locales. + static const List supportedLocales = [ + Locale('en'), + Locale('zh') + ]; + + /// No description provided for @appTitle. + /// + /// In en, this message translates to: + /// **'WeChat Camera Picker Demo'** + String get appTitle; + + /// No description provided for @appVersion. + /// + /// In en, this message translates to: + /// **'Version: {version}'** + String appVersion(Object version); + + /// No description provided for @appVersionUnknown. + /// + /// In en, this message translates to: + /// **'unknown'** + String get appVersionUnknown; + + /// No description provided for @selectedAssetsText. + /// + /// In en, this message translates to: + /// **'Selected Assets'** + String get selectedAssetsText; + + /// No description provided for @pickMethodNotice. + /// + /// In en, this message translates to: + /// **'Pickers in this page are located at the {dist}, defined by `pickMethods`.'** + String pickMethodNotice(Object dist); + + /// No description provided for @pickMethodPhotosName. + /// + /// In en, this message translates to: + /// **'Taking photos'** + String get pickMethodPhotosName; + + /// No description provided for @pickMethodPhotosDescription. + /// + /// In en, this message translates to: + /// **'Use cameras only to take photos.'** + String get pickMethodPhotosDescription; + + /// No description provided for @pickMethodPhotosAndVideosName. + /// + /// In en, this message translates to: + /// **'Taking photos and videos'** + String get pickMethodPhotosAndVideosName; + + /// No description provided for @pickMethodPhotosAndVideosDescription. + /// + /// In en, this message translates to: + /// **'Use cameras to take photos and videos.'** + String get pickMethodPhotosAndVideosDescription; + + /// No description provided for @pickMethodVideosName. + /// + /// In en, this message translates to: + /// **'Taking videos'** + String get pickMethodVideosName; + + /// No description provided for @pickMethodVideosDescription. + /// + /// In en, this message translates to: + /// **'Use cameras only to take videos.'** + String get pickMethodVideosDescription; + + /// No description provided for @pickMethodVideosByTapName. + /// + /// In en, this message translates to: + /// **'Taking videos by tap'** + String get pickMethodVideosByTapName; + + /// No description provided for @pickMethodVideosByTapDescription. + /// + /// In en, this message translates to: + /// **'Use cameras only to take videos, but not with long-press, just a single tap.'** + String get pickMethodVideosByTapDescription; + + /// No description provided for @pickMethodSilenceRecordingName. + /// + /// In en, this message translates to: + /// **'Silence recording'** + String get pickMethodSilenceRecordingName; + + /// No description provided for @pickMethodSilenceRecordingDescription. + /// + /// In en, this message translates to: + /// **'Make recordings silent.'** + String get pickMethodSilenceRecordingDescription; + + /// No description provided for @pickMethodAutoPreviewVideosName. + /// + /// In en, this message translates to: + /// **'Auto preview videos'** + String get pickMethodAutoPreviewVideosName; + + /// No description provided for @pickMethodAutoPreviewVideosDescription. + /// + /// In en, this message translates to: + /// **'Play videos automatically in the preview after captured.'** + String get pickMethodAutoPreviewVideosDescription; + + /// No description provided for @pickMethodNoDurationLimitName. + /// + /// In en, this message translates to: + /// **'No duration limit'** + String get pickMethodNoDurationLimitName; + + /// No description provided for @pickMethodNoDurationLimitDescription. + /// + /// In en, this message translates to: + /// **'Record as long as you with (if your device stays alive)...'** + String get pickMethodNoDurationLimitDescription; + + /// No description provided for @pickMethodCustomizableThemeName. + /// + /// In en, this message translates to: + /// **'Customizable theme (ThemeData)'** + String get pickMethodCustomizableThemeName; + + /// No description provided for @pickMethodCustomizableThemeDescription. + /// + /// In en, this message translates to: + /// **'Picking assets with the light theme or with a different color.'** + String get pickMethodCustomizableThemeDescription; + + /// No description provided for @pickMethodRotateInTurnsName. + /// + /// In en, this message translates to: + /// **'Rotate picker in turns'** + String get pickMethodRotateInTurnsName; + + /// No description provided for @pickMethodRotateInTurnsDescription. + /// + /// In en, this message translates to: + /// **'Rotate the picker layout in quarter turns, without the camera preview.'** + String get pickMethodRotateInTurnsDescription; + + /// No description provided for @pickMethodPreventScalingName. + /// + /// In en, this message translates to: + /// **'Prevent scaling for camera preview'** + String get pickMethodPreventScalingName; + + /// No description provided for @pickMethodPreventScalingDescription. + /// + /// In en, this message translates to: + /// **'Camera preview will not be scaled to cover the whole screen of the device, only fit for the raw aspect ratio.'** + String get pickMethodPreventScalingDescription; + + /// No description provided for @pickMethodLowerResolutionName. + /// + /// In en, this message translates to: + /// **'Lower resolutions'** + String get pickMethodLowerResolutionName; + + /// No description provided for @pickMethodLowerResolutionDescription. + /// + /// In en, this message translates to: + /// **'Use a lower resolution preset might be helpful in some specific scenarios.'** + String get pickMethodLowerResolutionDescription; + + /// No description provided for @pickMethodPreferFrontCameraName. + /// + /// In en, this message translates to: + /// **'Prefer front camera'** + String get pickMethodPreferFrontCameraName; + + /// No description provided for @pickMethodPreferFrontCameraDescription. + /// + /// In en, this message translates to: + /// **'Use the front camera as the preferred lens direction if the device supports.'** + String get pickMethodPreferFrontCameraDescription; + + /// No description provided for @pickMethodPreferFlashlightOnName. + /// + /// In en, this message translates to: + /// **'Prefer flashlight always on'** + String get pickMethodPreferFlashlightOnName; + + /// No description provided for @pickMethodPreferFlashlightOnDescription. + /// + /// In en, this message translates to: + /// **'Prefer to keep using the flashlight during captures.'** + String get pickMethodPreferFlashlightOnDescription; + + /// No description provided for @pickMethodForegroundBuilderName. + /// + /// In en, this message translates to: + /// **'Foreground builder'** + String get pickMethodForegroundBuilderName; + + /// No description provided for @pickMethodForegroundBuilderDescription. + /// + /// In en, this message translates to: + /// **'Build your widgets with the given CameraController on the top of the camera preview.'** + String get pickMethodForegroundBuilderDescription; +} + +class _AppLocalizationsDelegate extends LocalizationsDelegate { + const _AppLocalizationsDelegate(); + + @override + Future load(Locale locale) { + return SynchronousFuture(lookupAppLocalizations(locale)); + } + + @override + bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode); + + @override + bool shouldReload(_AppLocalizationsDelegate old) => false; +} + +AppLocalizations lookupAppLocalizations(Locale locale) { + + + // Lookup logic when only language code is specified. + switch (locale.languageCode) { + case 'en': return AppLocalizationsEn(); + case 'zh': return AppLocalizationsZh(); + } + + throw FlutterError( + 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' + 'an issue with the localizations generation tool. Please file an issue ' + 'on GitHub with a reproducible sample app and the gen-l10n configuration ' + 'that was used.' + ); +} diff --git a/example/lib/l10n/gen/app_localizations_en.dart b/example/lib/l10n/gen/app_localizations_en.dart new file mode 100644 index 0000000..5e315e9 --- /dev/null +++ b/example/lib/l10n/gen/app_localizations_en.dart @@ -0,0 +1,109 @@ +import 'app_localizations.dart'; + +/// The translations for English (`en`). +class AppLocalizationsEn extends AppLocalizations { + AppLocalizationsEn([String locale = 'en']) : super(locale); + + @override + String get appTitle => 'WeChat Camera Picker Demo'; + + @override + String appVersion(Object version) { + return 'Version: $version'; + } + + @override + String get appVersionUnknown => 'unknown'; + + @override + String get selectedAssetsText => 'Selected Assets'; + + @override + String pickMethodNotice(Object dist) { + return 'Pickers in this page are located at the $dist, defined by `pickMethods`.'; + } + + @override + String get pickMethodPhotosName => 'Taking photos'; + + @override + String get pickMethodPhotosDescription => 'Use cameras only to take photos.'; + + @override + String get pickMethodPhotosAndVideosName => 'Taking photos and videos'; + + @override + String get pickMethodPhotosAndVideosDescription => 'Use cameras to take photos and videos.'; + + @override + String get pickMethodVideosName => 'Taking videos'; + + @override + String get pickMethodVideosDescription => 'Use cameras only to take videos.'; + + @override + String get pickMethodVideosByTapName => 'Taking videos by tap'; + + @override + String get pickMethodVideosByTapDescription => 'Use cameras only to take videos, but not with long-press, just a single tap.'; + + @override + String get pickMethodSilenceRecordingName => 'Silence recording'; + + @override + String get pickMethodSilenceRecordingDescription => 'Make recordings silent.'; + + @override + String get pickMethodAutoPreviewVideosName => 'Auto preview videos'; + + @override + String get pickMethodAutoPreviewVideosDescription => 'Play videos automatically in the preview after captured.'; + + @override + String get pickMethodNoDurationLimitName => 'No duration limit'; + + @override + String get pickMethodNoDurationLimitDescription => 'Record as long as you with (if your device stays alive)...'; + + @override + String get pickMethodCustomizableThemeName => 'Customizable theme (ThemeData)'; + + @override + String get pickMethodCustomizableThemeDescription => 'Picking assets with the light theme or with a different color.'; + + @override + String get pickMethodRotateInTurnsName => 'Rotate picker in turns'; + + @override + String get pickMethodRotateInTurnsDescription => 'Rotate the picker layout in quarter turns, without the camera preview.'; + + @override + String get pickMethodPreventScalingName => 'Prevent scaling for camera preview'; + + @override + String get pickMethodPreventScalingDescription => 'Camera preview will not be scaled to cover the whole screen of the device, only fit for the raw aspect ratio.'; + + @override + String get pickMethodLowerResolutionName => 'Lower resolutions'; + + @override + String get pickMethodLowerResolutionDescription => 'Use a lower resolution preset might be helpful in some specific scenarios.'; + + @override + String get pickMethodPreferFrontCameraName => 'Prefer front camera'; + + @override + String get pickMethodPreferFrontCameraDescription => 'Use the front camera as the preferred lens direction if the device supports.'; + + @override + String get pickMethodPreferFlashlightOnName => 'Prefer flashlight always on'; + + @override + String get pickMethodPreferFlashlightOnDescription => 'Prefer to keep using the flashlight during captures.'; + + @override + String get pickMethodForegroundBuilderName => 'Foreground builder'; + + @override + String get pickMethodForegroundBuilderDescription => 'Build your widgets with the given CameraController on the top of the camera preview.'; +} diff --git a/example/lib/l10n/gen/app_localizations_untranslated.json b/example/lib/l10n/gen/app_localizations_untranslated.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/example/lib/l10n/gen/app_localizations_untranslated.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/example/lib/l10n/gen/app_localizations_zh.dart b/example/lib/l10n/gen/app_localizations_zh.dart new file mode 100644 index 0000000..ad65fa6 --- /dev/null +++ b/example/lib/l10n/gen/app_localizations_zh.dart @@ -0,0 +1,109 @@ +import 'app_localizations.dart'; + +/// The translations for Chinese (`zh`). +class AppLocalizationsZh extends AppLocalizations { + AppLocalizationsZh([String locale = 'zh']) : super(locale); + + @override + String get appTitle => 'WeChat Camera Picker 示例'; + + @override + String appVersion(Object version) { + return '版本:$version'; + } + + @override + String get appVersionUnknown => '未知'; + + @override + String get selectedAssetsText => '已选的资源'; + + @override + String pickMethodNotice(Object dist) { + return '该页面的所有选择器的代码位于 $dist,由 `pickMethods` 定义。'; + } + + @override + String get pickMethodPhotosName => '拍照'; + + @override + String get pickMethodPhotosDescription => '使用相机拍照。'; + + @override + String get pickMethodPhotosAndVideosName => '拍照和录像'; + + @override + String get pickMethodPhotosAndVideosDescription => '使用相机进行拍照和录像。'; + + @override + String get pickMethodVideosName => '录像'; + + @override + String get pickMethodVideosDescription => '使用相机录像。'; + + @override + String get pickMethodVideosByTapName => '轻触录像'; + + @override + String get pickMethodVideosByTapDescription => '轻触录像按钮进行录像,而不是长按。'; + + @override + String get pickMethodSilenceRecordingName => '静音录像'; + + @override + String get pickMethodSilenceRecordingDescription => '录像时不录制声音。'; + + @override + String get pickMethodAutoPreviewVideosName => '自动预览录制的视频'; + + @override + String get pickMethodAutoPreviewVideosDescription => '预览录制的视频时,自动播放。'; + + @override + String get pickMethodNoDurationLimitName => '无时长限制录像'; + + @override + String get pickMethodNoDurationLimitDescription => '想录多久,就录多久(只要手机健在)。'; + + @override + String get pickMethodCustomizableThemeName => '自定义主题 (ThemeData)'; + + @override + String get pickMethodCustomizableThemeDescription => '可以用亮色或其他颜色及自定义的主题进行选择。'; + + @override + String get pickMethodRotateInTurnsName => '旋转选择器的布局'; + + @override + String get pickMethodRotateInTurnsDescription => '顺时针旋转选择器的元素布局,不旋转相机视图。'; + + @override + String get pickMethodPreventScalingName => '禁止缩放相机预览'; + + @override + String get pickMethodPreventScalingDescription => '相机预览视图不会被放大到覆盖整个屏幕,仅适应原始的预览比例。'; + + @override + String get pickMethodLowerResolutionName => '低分辨率拍照'; + + @override + String get pickMethodLowerResolutionDescription => '某些情况或机型使用低分辨率拍照会有稳定性改善。'; + + @override + String get pickMethodPreferFrontCameraName => '首选前置摄像头'; + + @override + String get pickMethodPreferFrontCameraDescription => '在设备支持时首选使用前置摄像头。'; + + @override + String get pickMethodPreferFlashlightOnName => '首选闪光灯始终启用'; + + @override + String get pickMethodPreferFlashlightOnDescription => '在设备支持时首选闪光灯始终启用。'; + + @override + String get pickMethodForegroundBuilderName => '构建前景'; + + @override + String get pickMethodForegroundBuilderDescription => '通过 CameraController 构建在相机预览部分的前景 widget。'; +} diff --git a/example/lib/main.dart b/example/lib/main.dart index 5fe965b..bcb4381 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -6,14 +6,10 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; import 'extensions/color_extension.dart'; - -/// Common picking methods are defined in [pickMethods]. -/// 常见的选择器调用方式定义在 [pickMethods]。 -import 'models/picker_method.dart'; - +import 'extensions/l10n_extensions.dart'; +import 'l10n/gen/app_localizations.dart'; import 'pages/splash_page.dart'; const Color themeColor = Color(0xff00bc56); @@ -33,7 +29,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'WeChat Camera Picker Demo', + onGenerateTitle: (BuildContext context) => context.l10n.appTitle, theme: ThemeData( brightness: MediaQueryData.fromWindow(ui.window).platformBrightness, primarySwatch: themeColor.swatch, @@ -42,16 +38,8 @@ class MyApp extends StatelessWidget { ), ), home: const SplashPage(), - localizationsDelegates: const >[ - GlobalWidgetsLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: const [ - Locale('en'), // English - Locale('zh'), // Chinese - ], - locale: const Locale('en'), + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, ); } } diff --git a/example/lib/models/picker_method.dart b/example/lib/models/picker_method.dart index 05ac113..01ecab5 100644 --- a/example/lib/models/picker_method.dart +++ b/example/lib/models/picker_method.dart @@ -5,20 +5,22 @@ import 'package:flutter/material.dart'; import 'package:wechat_camera_picker/wechat_camera_picker.dart'; +import '../extensions/l10n_extensions.dart'; + /// Provide common usages of the picker. /// 提供常见的选择器调用方式。 -List get pickMethods { +List pickMethods(BuildContext context) { return [ PickMethod( icon: '📷', - name: 'Taking photos', - description: 'Use cameras only to take photos.', + name: context.l10n.pickMethodPhotosName, + description: context.l10n.pickMethodPhotosDescription, method: (BuildContext context) => CameraPicker.pickFromCamera(context), ), PickMethod( icon: '📹', - name: 'Taking photos and videos', - description: 'Use cameras to take photos and videos.', + name: context.l10n.pickMethodPhotosAndVideosName, + description: context.l10n.pickMethodPhotosAndVideosDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig(enableRecording: true), @@ -26,8 +28,8 @@ List get pickMethods { ), PickMethod( icon: '🎥', - name: 'Taking videos', - description: 'Use cameras only to take videos.', + name: context.l10n.pickMethodVideosName, + description: context.l10n.pickMethodVideosDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -38,9 +40,8 @@ List get pickMethods { ), PickMethod( icon: '📽', - name: 'Taking videos by tap', - description: 'Use cameras only to take videos, but not with long-press, ' - 'just a single tap.', + name: context.l10n.pickMethodVideosByTapName, + description: context.l10n.pickMethodVideosByTapDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -52,8 +53,8 @@ List get pickMethods { ), PickMethod( icon: '🈲', - name: 'Silence recording', - description: 'Make recordings silent.', + name: context.l10n.pickMethodSilenceRecordingName, + description: context.l10n.pickMethodSilenceRecordingDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -66,8 +67,8 @@ List get pickMethods { ), PickMethod( icon: '▶️', - name: 'Auto preview videos', - description: 'Play videos automatically in the preview after captured.', + name: context.l10n.pickMethodAutoPreviewVideosName, + description: context.l10n.pickMethodAutoPreviewVideosDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -80,9 +81,8 @@ List get pickMethods { ), PickMethod( icon: '⏳', - name: 'No duration limit', - description: - 'Record as long as you wish (if your device can stay alive)...', + name: context.l10n.pickMethodNoDurationLimitName, + description: context.l10n.pickMethodNoDurationLimitDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -95,8 +95,8 @@ List get pickMethods { ), PickMethod( icon: '🎨', - name: 'Custom theme', - description: 'Use a customized (different main color) theme.', + name: context.l10n.pickMethodCustomizableThemeName, + description: context.l10n.pickMethodCustomizableThemeDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: CameraPickerConfig( @@ -106,8 +106,8 @@ List get pickMethods { ), PickMethod( icon: '↩️', - name: 'Rotate picker in turns', - description: 'Rotate the picker layout in quarter turns.', + name: context.l10n.pickMethodRotateInTurnsName, + description: context.l10n.pickMethodRotateInTurnsDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig(cameraQuarterTurns: 1), @@ -115,9 +115,8 @@ List get pickMethods { ), PickMethod( icon: '🔍', - name: 'Prevent scaling for camera preview', - description: 'Camera preview will not be scaled to cover ' - 'the whole screen of the device, only fit with the raw size.', + name: context.l10n.pickMethodPreventScalingName, + description: context.l10n.pickMethodPreventScalingDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig(enableScaledPreview: false), @@ -125,9 +124,8 @@ List get pickMethods { ), PickMethod( icon: '🌀', - name: 'Lower resolutions', - description: 'Use a lower resolution preset might be helpful ' - 'in some specific scenarios.', + name: context.l10n.pickMethodLowerResolutionName, + description: context.l10n.pickMethodLowerResolutionDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -137,9 +135,8 @@ List get pickMethods { ), PickMethod( icon: '🤳', - name: 'Prefer front camera', - description: 'Use the front camera as the preferred lens direction, ' - 'if the device has a front camera.', + name: context.l10n.pickMethodPreferFrontCameraName, + description: context.l10n.pickMethodPreferFrontCameraDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: const CameraPickerConfig( @@ -147,10 +144,21 @@ List get pickMethods { ), ), ), + PickMethod( + icon: '📸', + name: context.l10n.pickMethodPreferFlashlightOnName, + description: context.l10n.pickMethodPreferFlashlightOnDescription, + method: (BuildContext context) => CameraPicker.pickFromCamera( + context, + pickerConfig: const CameraPickerConfig( + preferredFlashMode: FlashMode.always, + ), + ), + ), PickMethod( icon: '🪄', - name: 'Foreground builder', - description: 'Build your widgets with the given CameraValue.', + name: context.l10n.pickMethodForegroundBuilderName, + description: context.l10n.pickMethodForegroundBuilderDescription, method: (BuildContext context) => CameraPicker.pickFromCamera( context, pickerConfig: CameraPickerConfig( diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index 9c9dbde..becce2d 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/semantics.dart'; import 'package:flutter/services.dart'; import 'package:wechat_camera_picker/wechat_camera_picker.dart'; +import '../extensions/l10n_extensions.dart'; import '../main.dart'; import '../models/picker_method.dart'; import '../widgets/method_list_view.dart'; @@ -56,15 +57,17 @@ class _MyHomePageState extends State { Semantics( sortKey: const OrdinalSortKey(0), child: Text( - 'WeChat Camera Picker', - style: Theme.of(context).textTheme.headline6, + context.l10n.appTitle, + style: Theme.of(context).textTheme.titleLarge, ), ), Semantics( sortKey: const OrdinalSortKey(0.1), child: Text( - 'Version: ${packageVersion ?? 'unknown'}', - style: Theme.of(context).textTheme.caption, + context.l10n.appVersion( + packageVersion ?? context.l10n.appVersionUnknown, + ), + style: Theme.of(context).textTheme.bodySmall, ), ), ], @@ -86,9 +89,17 @@ class _MyHomePageState extends State { child: Column( children: [ header(context), + Padding( + padding: const EdgeInsets.all(20.0), + child: Text( + context.l10n.pickMethodNotice( + 'lib/models/picker_method.dart', + ), + ), + ), Expanded( child: MethodListView( - pickMethods: pickMethods, + pickMethods: pickMethods(context), onSelectMethod: selectAssets, ), ), diff --git a/example/lib/widgets/selected_assets_view.dart b/example/lib/widgets/selected_assets_view.dart index 4585f1e..4a63628 100644 --- a/example/lib/widgets/selected_assets_view.dart +++ b/example/lib/widgets/selected_assets_view.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:wechat_camera_picker/wechat_camera_picker.dart'; +import '../extensions/l10n_extensions.dart'; import 'asset_widget_builder.dart'; import 'preview_asset_widget.dart'; @@ -102,7 +103,7 @@ class SelectedAssetView extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - const Text('Selected Assets'), + Text(context.l10n.selectedAssetsText), Padding( padding: const EdgeInsetsDirectional.only(start: 10), child: Icon(