├── .gitattributes ├── .github └── stale.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── SECURITY.md ├── analysis_options.yaml ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── dev │ │ │ │ │ └── leadcode │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ └── i18n │ │ ├── ar.json │ │ ├── en.json │ │ ├── es.json │ │ └── ru.json ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner-Bridging-Header.h │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.yaml ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ └── Icon-512.png │ ├── index.html │ └── manifest.json └── windows │ ├── .gitignore │ ├── CMakeLists.txt │ ├── flutter │ ├── CMakeLists.txt │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── generated_plugins.cmake │ └── runner │ ├── CMakeLists.txt │ ├── Runner.rc │ ├── flutter_window.cpp │ ├── flutter_window.h │ ├── main.cpp │ ├── resource.h │ ├── resources │ └── app_icon.ico │ ├── run_loop.cpp │ ├── run_loop.h │ ├── runner.exe.manifest │ ├── utils.cpp │ ├── utils.h │ ├── win32_window.cpp │ └── win32_window.h ├── lib ├── flutter_translate.dart └── src │ ├── constants │ └── constants.dart │ ├── delegates │ └── localization_delegate.dart │ ├── interfaces │ └── translate_preferences.dart │ ├── services │ ├── locale_file_service.dart │ ├── locale_service.dart │ ├── localization.dart │ └── localization_configuration.dart │ ├── utils │ ├── device_locale.dart │ └── utils.dart │ ├── validators │ └── configuration_validator.dart │ └── widgets │ ├── localization_provider.dart │ ├── localized_app.dart │ └── localized_app_state.dart ├── pubspec.yaml └── resources ├── gifs └── flutter_translate_screen.gif └── images └── flutter_translate.png /.gitattributes: -------------------------------------------------------------------------------- 1 | *.cmake linguist-detectable=false 2 | *.h linguist-detectable=false 3 | *.cpp linguist-detectable=false -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .packages 28 | .pub-cache/ 29 | .pub/ 30 | build/ 31 | 32 | # Android related 33 | **/android/**/gradle-wrapper.jar 34 | **/android/.gradle 35 | **/android/captures/ 36 | **/android/gradlew 37 | **/android/gradlew.bat 38 | **/android/local.properties 39 | **/android/**/GeneratedPluginRegistrant.java 40 | 41 | # iOS/XCode related 42 | **/ios/**/*.mode1v3 43 | **/ios/**/*.mode2v3 44 | **/ios/**/*.moved-aside 45 | **/ios/**/*.pbxuser 46 | **/ios/**/*.perspectivev3 47 | **/ios/**/*sync/ 48 | **/ios/**/.sconsign.dblite 49 | **/ios/**/.tags* 50 | **/ios/**/.vagrant/ 51 | **/ios/**/DerivedData/ 52 | **/ios/**/Icon? 53 | **/ios/**/Pods/ 54 | **/ios/**/.symlinks/ 55 | **/ios/**/profile 56 | **/ios/**/xcuserdata 57 | **/ios/.generated/ 58 | **/ios/Flutter/App.framework 59 | **/ios/Flutter/Flutter.framework 60 | **/ios/Flutter/Generated.xcconfig 61 | **/ios/Flutter/app.flx 62 | **/ios/Flutter/app.zip 63 | **/ios/Flutter/flutter_assets/ 64 | **/ios/Flutter/flutter_export_environment.sh 65 | **/ios/ServiceDefinitions.json 66 | **/ios/Runner/GeneratedPluginRegistrant.* 67 | 68 | # Exceptions to above rules. 69 | !**/ios/**/default.mode1v3 70 | !**/ios/**/default.mode2v3 71 | !**/ios/**/default.pbxuser 72 | !**/ios/**/default.perspectivev3 73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 74 | pubspec.lock 75 | example_static_keys/lib/generated_plugin_registrant.dart 76 | example_static_keys/.flutter-plugins-dependencies 77 | example/lib/generated_plugin_registrant.dart 78 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: cc949a8e8b9cf394b9290a8e80f87af3e207dce5 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.0] 2 | 3 | - Initial release. 4 | 5 | ## [1.0.1] 6 | 7 | - Removed the flutter_localizations dependency. 8 | 9 | ## [1.0.2] 10 | 11 | - Simplified the localization initialization. 12 | 13 | ## [1.1.0] 14 | 15 | - Implemented a global translate method. 16 | - Removed the static Translate class. 17 | - Localization is now a singleton. 18 | 19 | ## [1.2.0] 20 | 21 | - Implemented pluralization. 22 | - Fixed multiple issues. 23 | - translate, translatePlural and changeLanguage methods are now global. 24 | 25 | ## [1.2.2] 26 | 27 | - Missing localizations now return the full key path. 28 | 29 | ## [1.2.5] 30 | 31 | - Fixed possible exception when adding an extra slash to the ```basePath``` 32 | 33 | ## [1.3.0] 34 | 35 | - Implemented the onLocaleChanged callback 36 | 37 | ## [1.3.1] 38 | 39 | - Implemented the localeToString method 40 | 41 | ## [1.3.2] 42 | 43 | - Fixed some callback issues for onLocaleChanged 44 | 45 | ## [1.4.0] 46 | 47 | - Implemented support for automatically saving & restoring the selected locale using shared preferences 48 | 49 | ## [1.4.0+1] 50 | 51 | - Added the Awesome Flutter badge 52 | 53 | ## [1.4.0+2] 54 | 55 | - Fixed the example to adapt the changes to BinaryMessenger (https://github.com/flutter/flutter/pull/38464) 56 | 57 | ## [1.5.0] 58 | 59 | - Fixed the blackscreen issue on startup 60 | - Fixed the iOS issue regarding the device locale 61 | - The current device locale is now used on startup 62 | 63 | ## [1.5.1] 64 | 65 | - Updated the flutter_device_locale dependency to avoid a possible exception 66 | - Updated the example to AndroidX 67 | 68 | ## [1.5.2] 69 | 70 | - Updated the flutter_device_locale version 71 | 72 | ## [1.5.3] 73 | 74 | - Renamed packages, updated license and links 75 | 76 | ## [1.5.7] 77 | 78 | - Updated the examples 79 | - Fixed some issues with flutter_device_locale and swift 80 | 81 | ## [1.6.0] 82 | 83 | - Web applications are now supported 84 | - Updated the examples with web support 85 | 86 | ## [2.0.0] 87 | 88 | - Removed flutter_device_locale dependency 89 | - The native flutter locale retrieval method is now used 90 | - Added support for desktop 91 | - Added examples for windows desktop 92 | 93 | ## [2.0.1] 94 | 95 | - Fixed web support 96 | 97 | ## [3.0.0] 98 | 99 | - Null safety support 100 | 101 | ## [3.0.1] 102 | 103 | - Code format 104 | 105 | ## [3.1.0] 106 | 107 | - Updated dependencies 108 | 109 | ## [4.0.0] 110 | 111 | - Plurals functionality is now based on Intl rules (https://api.flutter.dev/flutter/intl/Intl/plural.html) 112 | - Supported formats are: zero, one, two, few, many, other 113 | 114 | ## [4.0.2] 115 | 116 | - Fixed null safety compile issue 117 | 118 | ## [4.0.3] 119 | 120 | - Fixed null-aware operation exception 121 | 122 | ## [4.0.4] 123 | 124 | - Bump intl version to support latest Flutter version 125 | 126 | ## [4.1.0] 127 | 128 | - Upgraded packages and SDK version -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jesway Labs, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [](https://github.com/Jesway/Flutter-Translate/) 3 | 4 | [![pub package](https://img.shields.io/pub/v/flutter_translate.svg?color=important)](https://pub.dev/packages/flutter_translate) 5 | 6 | Awesome Flutter 7 | 8 | [![License: MIT](https://img.shields.io/badge/License-MIT-ff69b4.svg)](https://github.com/Jesway/Flutter-Translate/blob/master/LICENSE) 9 | [![Flutter.io](https://img.shields.io/badge/Flutter-Website-deepskyblue.svg)](https://flutter.io/) 10 | 11 | --- 12 | 13 | Flutter Translate is a fully featured localization / internationalization (i18n) library for Flutter. 14 | 15 | It lets you define translations for your content in different languages and switch between them easily. 16 | 17 | ## Example 18 | 19 | 20 | ## Features 21 | 22 | * Very easy to use 23 | * ```Mobile```, ```Web``` and ```Desktop``` support 24 | * ```Pluralization``` and ```Duals``` support 25 | * Supports both ``languageCode (en)`` and ``languageCode_countryCode (en_US)`` locale formats 26 | * Automatically ```save & restore``` the selected locale [with a simple implementation](https://github.com/Jesway/Flutter-Translate/wiki/2.-Automatically-saving-&-restoring-the-selected-locale) 27 | * Full support for ```right-to-left``` locales 28 | * ``Fallback`` locale support in case the system locale is unsupported 29 | * Supports both ``inline or nested`` JSON 30 | 31 | ## Documentation 32 | 33 | Complete documentation is available [on the wiki page](https://github.com/Jesway/Flutter-Translate/wiki). 34 | 35 | To get started please see [Installation, Configuration & Usage](https://github.com/Jesway/Flutter-Translate/wiki/1.-Installation,-Configuration-&-Usage). 36 | 37 | ## Example 38 | 39 | https://github.com/Jesway/Flutter-Translate/tree/master/example 40 | 41 | ## Issues 42 | Please file any issues, bugs or feature request [here](https://github.com/Jesway/Flutter-Translate/issues). 43 | 44 | ## License 45 | 46 | This project is licensed under the [MIT License](https://github.com/Jesway/Flutter-Translate/blob/master/LICENSE) 47 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | In our commitment to maintain the security of the Flutter Translate project, we focus on providing security updates only to the most recent MAJOR.MINOR version. We do not backport security patches to earlier versions. To ensure you have the latest security enhancements, always keep your Flutter Translate installation updated to the latest release. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Should you discover a security vulnerability within Flutter Translate, we encourage a responsible disclosure. Please send a detailed report of your findings to security@jesway.com. Our team will promptly investigate and address the issue as swiftly as possible. 10 | 11 | We greatly appreciate the efforts of individuals who contribute to the security of our project. While we currently do not offer a bounty program, every report, be it a minor bug or a significant security flaw, is invaluable in enhancing Flutter Translate for all users. We extend our heartfelt thanks to those who assist us in this crucial aspect of software maintenance. 12 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | # enable-experiment: 3 | # - non-nullable 4 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Generated.xcconfig 62 | **/ios/Flutter/app.flx 63 | **/ios/Flutter/app.zip 64 | **/ios/Flutter/flutter_assets/ 65 | **/ios/Flutter/flutter_export_environment.sh 66 | **/ios/ServiceDefinitions.json 67 | **/ios/Runner/GeneratedPluginRegistrant.* 68 | 69 | # Exceptions to above rules. 70 | !**/ios/**/default.mode1v3 71 | !**/ios/**/default.mode2v3 72 | !**/ios/**/default.pbxuser 73 | !**/ios/**/default.perspectivev3 74 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 75 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: cc949a8e8b9cf394b9290a8e80f87af3e207dce5 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | Example project for the flutter_translate library 4 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "dev.com.jesway.example" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 60 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 61 | } 62 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 13 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/dev/leadcode/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dev.com.jesway.example; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | 3 | android.enableR8=true 4 | android.useAndroidX=true 5 | android.enableJetifier=true 6 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/assets/i18n/ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_bar": 3 | { 4 | "title": "مرحباً بك في الصفحة الرئيسية" 5 | }, 6 | "button": 7 | { 8 | "cancel": "إلغاء", 9 | "change_language": "تغيير اللغة" 10 | }, 11 | "language": 12 | { 13 | "name": 14 | { 15 | "en": "الانجليزية", 16 | "es": "الاسبانية", 17 | "fa": "الفارسية", 18 | "ar": "العربية", 19 | "ru": "الروسية" 20 | }, 21 | "selected_message": "اللغة المختارة حالياً هي {language}", 22 | "selection": 23 | { 24 | "message": "برجاء إختيار لغة من القائمة", 25 | "title": "إختيار اللغة" 26 | } 27 | }, 28 | "plural": 29 | { 30 | "demo": 31 | { 32 | "zero": "برجاء البدء في الضغط على زر الإضافة", 33 | "one": "لقد ضغطت الزر مرة", 34 | "two": "لقد ضغطت الزر مرتين", 35 | "other": "لقد ضغطت الزر {{value}} مرة" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_bar": 3 | { 4 | "title": "Welcome to the home page" 5 | }, 6 | "button": 7 | { 8 | "cancel": "Cancel", 9 | "change_language": "Change Language" 10 | }, 11 | "language": 12 | { 13 | "name": 14 | { 15 | "en": "English", 16 | "es": "Spanish", 17 | "fa": "Persian", 18 | "ar": "Arabic", 19 | "ru": "Russian" 20 | }, 21 | "selected_message": "Currently selected language is {language}", 22 | "selection": 23 | { 24 | "message": "Please select a language from the list", 25 | "title": "Language Selection" 26 | } 27 | }, 28 | "plural": 29 | { 30 | "demo": 31 | { 32 | "zero": "Please start pushing the 'plus' button.", 33 | "one": "You have pushed the button one time.", 34 | "two": "You have pushed the button two times.", 35 | "other": "You have pushed the button {{value}} times." 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/assets/i18n/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_bar": 3 | { 4 | "title": "Bienvenido a la página de inicio" 5 | }, 6 | "button": 7 | { 8 | "cancel": "Cancelar", 9 | "change_language": "Cambiar idioma" 10 | }, 11 | "language": 12 | { 13 | "name": 14 | { 15 | "en": "Inglés", 16 | "es": "Español", 17 | "fa": "Persa", 18 | "ar": "Arábica", 19 | "ru": "Ruso" 20 | }, 21 | "selected_message": "El idioma seleccionado actualmente es {language}", 22 | "selection": 23 | { 24 | "message": "Por favor seleccione un idioma de la lista", 25 | "title": "Selección de idioma" 26 | } 27 | }, 28 | "plural": 29 | { 30 | "demo": 31 | { 32 | "zero": "Por favor, comience a presionar el botón 'más'.", 33 | "one": "Has pulsado el botón una vez.", 34 | "two": "Has pulsado el botón dos veces.", 35 | "other": "Ha pulsado el botón {{value}} veces." 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /example/assets/i18n/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_bar": 3 | { 4 | "title": "Приветствуем на домашней странице" 5 | }, 6 | "button": 7 | { 8 | "cancel": "Отмена", 9 | "change_language": "Сменить Язык" 10 | }, 11 | "language": 12 | { 13 | "name": 14 | { 15 | "en": "Английский", 16 | "es": "Испанский", 17 | "fa": "Персидский", 18 | "ar": "Арабский", 19 | "ru": "Русский" 20 | }, 21 | "selected_message": "Текущий язык {language}", 22 | "selection": 23 | { 24 | "message": "Пожалуйста выберите язык из списка", 25 | "title": "Выбор Языка" 26 | } 27 | }, 28 | "plural": 29 | { 30 | "demo": 31 | { 32 | "zero": "Нажимайте кнопку 'плюс'.", 33 | "one": "Кнопка плюс нажата {{value}} раз.", 34 | "two": "Кнопка плюс нажата {{value}} раза.", 35 | "few": "Кнопка плюс нажата {{value}} раза.", 36 | "many": "Кнопка плюс нажата {{value}} раз.", 37 | "other": "Кнопка плюс нажата {{value}} раз." 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | 38 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 39 | # referring to absolute paths on developers' machines. 40 | system('rm -rf .symlinks') 41 | system('mkdir -p .symlinks/plugins') 42 | 43 | # Flutter Pods 44 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 45 | if generated_xcode_build_settings.empty? 46 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." 47 | end 48 | generated_xcode_build_settings.map { |p| 49 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 50 | symlink = File.join('.symlinks', 'flutter') 51 | File.symlink(File.dirname(p[:path]), symlink) 52 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 53 | end 54 | } 55 | 56 | # Plugin Pods 57 | plugin_pods = parse_KV_file('../.flutter-plugins') 58 | plugin_pods.map { |p| 59 | symlink = File.join('.symlinks', 'plugins', p[:name]) 60 | File.symlink(p[:path], symlink) 61 | pod p[:name], :path => File.join(symlink, 'ios') 62 | } 63 | end 64 | 65 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. 66 | install! 'cocoapods', :disable_input_output_paths => true 67 | 68 | post_install do |installer| 69 | installer.pods_project.targets.each do |target| 70 | target.build_configurations.each do |config| 71 | config.build_settings['ENABLE_BITCODE'] = 'NO' 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_device_locale (0.0.1): 4 | - Flutter 5 | 6 | DEPENDENCIES: 7 | - Flutter (from `.symlinks/flutter/ios`) 8 | - flutter_device_locale (from `.symlinks/plugins/flutter_device_locale/ios`) 9 | 10 | EXTERNAL SOURCES: 11 | Flutter: 12 | :path: ".symlinks/flutter/ios" 13 | flutter_device_locale: 14 | :path: ".symlinks/plugins/flutter_device_locale/ios" 15 | 16 | SPEC CHECKSUMS: 17 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 18 | flutter_device_locale: bd88cfdfdcae58b2a9d5ec05389fd99631c9dca7 19 | 20 | PODFILE CHECKSUM: b6a0a141693093b304368d08511b46cf3d1d0ac5 21 | 22 | COCOAPODS: 1.7.5 23 | -------------------------------------------------------------------------------- /example/ios/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 15 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 17 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 18 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 22 | A8AA48402C356A06BB6C7962 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BEEF21C6EB80CFD18AFE5862 /* Pods_Runner.framework */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXCopyFilesBuildPhase section */ 26 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 27 | isa = PBXCopyFilesBuildPhase; 28 | buildActionMask = 2147483647; 29 | dstPath = ""; 30 | dstSubfolderSpec = 10; 31 | files = ( 32 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 33 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 34 | ); 35 | name = "Embed Frameworks"; 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXCopyFilesBuildPhase section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 0A85A4DDB7F1858BC9F4D9DE /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 42 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 43 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 44 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 45 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 46 | 4EFAE310239288E3004A2075 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 96399B0060D9218C958054AE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 51 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 52 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 53 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 54 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 56 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | BEEF21C6EB80CFD18AFE5862 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | FB3F11CF9B1C7B3801980BAE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 70 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 71 | A8AA48402C356A06BB6C7962 /* Pods_Runner.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXFrameworksBuildPhase section */ 76 | 77 | /* Begin PBXGroup section */ 78 | 4AFE5892C413A9B5977EFCCD /* Pods */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | FB3F11CF9B1C7B3801980BAE /* Pods-Runner.debug.xcconfig */, 82 | 0A85A4DDB7F1858BC9F4D9DE /* Pods-Runner.release.xcconfig */, 83 | 96399B0060D9218C958054AE /* Pods-Runner.profile.xcconfig */, 84 | ); 85 | name = Pods; 86 | path = Pods; 87 | sourceTree = ""; 88 | }; 89 | 9740EEB11CF90186004384FC /* Flutter */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 3B80C3931E831B6300D905FE /* App.framework */, 93 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 94 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 95 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 96 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 97 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 98 | ); 99 | name = Flutter; 100 | sourceTree = ""; 101 | }; 102 | 97C146E51CF9000F007C117D = { 103 | isa = PBXGroup; 104 | children = ( 105 | 9740EEB11CF90186004384FC /* Flutter */, 106 | 97C146F01CF9000F007C117D /* Runner */, 107 | 97C146EF1CF9000F007C117D /* Products */, 108 | 4EFAE310239288E3004A2075 /* Runner-Bridging-Header.h */, 109 | 4AFE5892C413A9B5977EFCCD /* Pods */, 110 | AA946D38C45F9768443E1E10 /* Frameworks */, 111 | ); 112 | sourceTree = ""; 113 | }; 114 | 97C146EF1CF9000F007C117D /* Products */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 97C146EE1CF9000F007C117D /* Runner.app */, 118 | ); 119 | name = Products; 120 | sourceTree = ""; 121 | }; 122 | 97C146F01CF9000F007C117D /* Runner */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 126 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 127 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 128 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 129 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 130 | 97C147021CF9000F007C117D /* Info.plist */, 131 | 97C146F11CF9000F007C117D /* Supporting Files */, 132 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 133 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 134 | ); 135 | path = Runner; 136 | sourceTree = ""; 137 | }; 138 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 97C146F21CF9000F007C117D /* main.m */, 142 | ); 143 | name = "Supporting Files"; 144 | sourceTree = ""; 145 | }; 146 | AA946D38C45F9768443E1E10 /* Frameworks */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | BEEF21C6EB80CFD18AFE5862 /* Pods_Runner.framework */, 150 | ); 151 | name = Frameworks; 152 | sourceTree = ""; 153 | }; 154 | /* End PBXGroup section */ 155 | 156 | /* Begin PBXNativeTarget section */ 157 | 97C146ED1CF9000F007C117D /* Runner */ = { 158 | isa = PBXNativeTarget; 159 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 160 | buildPhases = ( 161 | 060A4CDD59E2722244CFDD0E /* [CP] Check Pods Manifest.lock */, 162 | 9740EEB61CF901F6004384FC /* Run Script */, 163 | 97C146EA1CF9000F007C117D /* Sources */, 164 | 97C146EB1CF9000F007C117D /* Frameworks */, 165 | 97C146EC1CF9000F007C117D /* Resources */, 166 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 167 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 168 | 1C681DAA28B4269152958D4A /* [CP] Embed Pods Frameworks */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | ); 174 | name = Runner; 175 | productName = Runner; 176 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 177 | productType = "com.apple.product-type.application"; 178 | }; 179 | /* End PBXNativeTarget section */ 180 | 181 | /* Begin PBXProject section */ 182 | 97C146E61CF9000F007C117D /* Project object */ = { 183 | isa = PBXProject; 184 | attributes = { 185 | LastUpgradeCheck = 1020; 186 | ORGANIZATIONNAME = "The Chromium Authors"; 187 | TargetAttributes = { 188 | 97C146ED1CF9000F007C117D = { 189 | CreatedOnToolsVersion = 7.3.1; 190 | LastSwiftMigration = 1120; 191 | }; 192 | }; 193 | }; 194 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 195 | compatibilityVersion = "Xcode 3.2"; 196 | developmentRegion = en; 197 | hasScannedForEncodings = 0; 198 | knownRegions = ( 199 | en, 200 | Base, 201 | ); 202 | mainGroup = 97C146E51CF9000F007C117D; 203 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 97C146ED1CF9000F007C117D /* Runner */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | 97C146EC1CF9000F007C117D /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 218 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 219 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 220 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 221 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | /* End PBXResourcesBuildPhase section */ 226 | 227 | /* Begin PBXShellScriptBuildPhase section */ 228 | 060A4CDD59E2722244CFDD0E /* [CP] Check Pods Manifest.lock */ = { 229 | isa = PBXShellScriptBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | ); 233 | inputFileListPaths = ( 234 | ); 235 | inputPaths = ( 236 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 237 | "${PODS_ROOT}/Manifest.lock", 238 | ); 239 | name = "[CP] Check Pods Manifest.lock"; 240 | outputFileListPaths = ( 241 | ); 242 | outputPaths = ( 243 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | shellPath = /bin/sh; 247 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 248 | showEnvVarsInLog = 0; 249 | }; 250 | 1C681DAA28B4269152958D4A /* [CP] Embed Pods Frameworks */ = { 251 | isa = PBXShellScriptBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | inputPaths = ( 256 | ); 257 | name = "[CP] Embed Pods Frameworks"; 258 | outputPaths = ( 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | shellPath = /bin/sh; 262 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 263 | showEnvVarsInLog = 0; 264 | }; 265 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 266 | isa = PBXShellScriptBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | ); 270 | inputPaths = ( 271 | ); 272 | name = "Thin Binary"; 273 | outputPaths = ( 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | shellPath = /bin/sh; 277 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 278 | }; 279 | 9740EEB61CF901F6004384FC /* Run Script */ = { 280 | isa = PBXShellScriptBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | ); 284 | inputPaths = ( 285 | ); 286 | name = "Run Script"; 287 | outputPaths = ( 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | shellPath = /bin/sh; 291 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 292 | }; 293 | /* End PBXShellScriptBuildPhase section */ 294 | 295 | /* Begin PBXSourcesBuildPhase section */ 296 | 97C146EA1CF9000F007C117D /* Sources */ = { 297 | isa = PBXSourcesBuildPhase; 298 | buildActionMask = 2147483647; 299 | files = ( 300 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 301 | 97C146F31CF9000F007C117D /* main.m in Sources */, 302 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | /* End PBXSourcesBuildPhase section */ 307 | 308 | /* Begin PBXVariantGroup section */ 309 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 310 | isa = PBXVariantGroup; 311 | children = ( 312 | 97C146FB1CF9000F007C117D /* Base */, 313 | ); 314 | name = Main.storyboard; 315 | sourceTree = ""; 316 | }; 317 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 318 | isa = PBXVariantGroup; 319 | children = ( 320 | 97C147001CF9000F007C117D /* Base */, 321 | ); 322 | name = LaunchScreen.storyboard; 323 | sourceTree = ""; 324 | }; 325 | /* End PBXVariantGroup section */ 326 | 327 | /* Begin XCBuildConfiguration section */ 328 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 329 | isa = XCBuildConfiguration; 330 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 331 | buildSettings = { 332 | ALWAYS_SEARCH_USER_PATHS = NO; 333 | CLANG_ANALYZER_NONNULL = YES; 334 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 335 | CLANG_CXX_LIBRARY = "libc++"; 336 | CLANG_ENABLE_MODULES = YES; 337 | CLANG_ENABLE_OBJC_ARC = YES; 338 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 339 | CLANG_WARN_BOOL_CONVERSION = YES; 340 | CLANG_WARN_COMMA = YES; 341 | CLANG_WARN_CONSTANT_CONVERSION = YES; 342 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INFINITE_RECURSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 349 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 350 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 351 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 352 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 353 | CLANG_WARN_STRICT_PROTOTYPES = YES; 354 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 355 | CLANG_WARN_UNREACHABLE_CODE = YES; 356 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 357 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 358 | COPY_PHASE_STRIP = NO; 359 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 360 | ENABLE_NS_ASSERTIONS = NO; 361 | ENABLE_STRICT_OBJC_MSGSEND = YES; 362 | GCC_C_LANGUAGE_STANDARD = gnu99; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 371 | MTL_ENABLE_DEBUG_INFO = NO; 372 | SDKROOT = iphoneos; 373 | TARGETED_DEVICE_FAMILY = "1,2"; 374 | VALIDATE_PRODUCT = YES; 375 | }; 376 | name = Profile; 377 | }; 378 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 379 | isa = XCBuildConfiguration; 380 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 381 | buildSettings = { 382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 383 | CLANG_ENABLE_MODULES = YES; 384 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 385 | ENABLE_BITCODE = NO; 386 | FRAMEWORK_SEARCH_PATHS = ( 387 | "$(inherited)", 388 | "$(PROJECT_DIR)/Flutter", 389 | ); 390 | INFOPLIST_FILE = Runner/Info.plist; 391 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 392 | LIBRARY_SEARCH_PATHS = ( 393 | "$(inherited)", 394 | "$(PROJECT_DIR)/Flutter", 395 | ); 396 | PRODUCT_BUNDLE_IDENTIFIER = dev.com.jesway.example; 397 | PRODUCT_NAME = "$(TARGET_NAME)"; 398 | SWIFT_OBJC_BRIDGING_HEADER = "Runner-Bridging-Header.h"; 399 | SWIFT_VERSION = 5.0; 400 | VERSIONING_SYSTEM = "apple-generic"; 401 | }; 402 | name = Profile; 403 | }; 404 | 97C147031CF9000F007C117D /* Debug */ = { 405 | isa = XCBuildConfiguration; 406 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 407 | buildSettings = { 408 | ALWAYS_SEARCH_USER_PATHS = NO; 409 | CLANG_ANALYZER_NONNULL = YES; 410 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 411 | CLANG_CXX_LIBRARY = "libc++"; 412 | CLANG_ENABLE_MODULES = YES; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 415 | CLANG_WARN_BOOL_CONVERSION = YES; 416 | CLANG_WARN_COMMA = YES; 417 | CLANG_WARN_CONSTANT_CONVERSION = YES; 418 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 419 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 420 | CLANG_WARN_EMPTY_BODY = YES; 421 | CLANG_WARN_ENUM_CONVERSION = YES; 422 | CLANG_WARN_INFINITE_RECURSION = YES; 423 | CLANG_WARN_INT_CONVERSION = YES; 424 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 425 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 426 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 427 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 428 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 429 | CLANG_WARN_STRICT_PROTOTYPES = YES; 430 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 431 | CLANG_WARN_UNREACHABLE_CODE = YES; 432 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 433 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 434 | COPY_PHASE_STRIP = NO; 435 | DEBUG_INFORMATION_FORMAT = dwarf; 436 | ENABLE_STRICT_OBJC_MSGSEND = YES; 437 | ENABLE_TESTABILITY = YES; 438 | GCC_C_LANGUAGE_STANDARD = gnu99; 439 | GCC_DYNAMIC_NO_PIC = NO; 440 | GCC_NO_COMMON_BLOCKS = YES; 441 | GCC_OPTIMIZATION_LEVEL = 0; 442 | GCC_PREPROCESSOR_DEFINITIONS = ( 443 | "DEBUG=1", 444 | "$(inherited)", 445 | ); 446 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 447 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 448 | GCC_WARN_UNDECLARED_SELECTOR = YES; 449 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 450 | GCC_WARN_UNUSED_FUNCTION = YES; 451 | GCC_WARN_UNUSED_VARIABLE = YES; 452 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 453 | MTL_ENABLE_DEBUG_INFO = YES; 454 | ONLY_ACTIVE_ARCH = YES; 455 | SDKROOT = iphoneos; 456 | TARGETED_DEVICE_FAMILY = "1,2"; 457 | }; 458 | name = Debug; 459 | }; 460 | 97C147041CF9000F007C117D /* Release */ = { 461 | isa = XCBuildConfiguration; 462 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 463 | buildSettings = { 464 | ALWAYS_SEARCH_USER_PATHS = NO; 465 | CLANG_ANALYZER_NONNULL = YES; 466 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 467 | CLANG_CXX_LIBRARY = "libc++"; 468 | CLANG_ENABLE_MODULES = YES; 469 | CLANG_ENABLE_OBJC_ARC = YES; 470 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 471 | CLANG_WARN_BOOL_CONVERSION = YES; 472 | CLANG_WARN_COMMA = YES; 473 | CLANG_WARN_CONSTANT_CONVERSION = YES; 474 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 475 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 476 | CLANG_WARN_EMPTY_BODY = YES; 477 | CLANG_WARN_ENUM_CONVERSION = YES; 478 | CLANG_WARN_INFINITE_RECURSION = YES; 479 | CLANG_WARN_INT_CONVERSION = YES; 480 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 481 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 482 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 483 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 484 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 485 | CLANG_WARN_STRICT_PROTOTYPES = YES; 486 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 487 | CLANG_WARN_UNREACHABLE_CODE = YES; 488 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 489 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 490 | COPY_PHASE_STRIP = NO; 491 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 492 | ENABLE_NS_ASSERTIONS = NO; 493 | ENABLE_STRICT_OBJC_MSGSEND = YES; 494 | GCC_C_LANGUAGE_STANDARD = gnu99; 495 | GCC_NO_COMMON_BLOCKS = YES; 496 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 497 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 498 | GCC_WARN_UNDECLARED_SELECTOR = YES; 499 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 500 | GCC_WARN_UNUSED_FUNCTION = YES; 501 | GCC_WARN_UNUSED_VARIABLE = YES; 502 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 503 | MTL_ENABLE_DEBUG_INFO = NO; 504 | SDKROOT = iphoneos; 505 | TARGETED_DEVICE_FAMILY = "1,2"; 506 | VALIDATE_PRODUCT = YES; 507 | }; 508 | name = Release; 509 | }; 510 | 97C147061CF9000F007C117D /* Debug */ = { 511 | isa = XCBuildConfiguration; 512 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 513 | buildSettings = { 514 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 515 | CLANG_ENABLE_MODULES = YES; 516 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 517 | ENABLE_BITCODE = NO; 518 | FRAMEWORK_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "$(PROJECT_DIR)/Flutter", 521 | ); 522 | INFOPLIST_FILE = Runner/Info.plist; 523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 524 | LIBRARY_SEARCH_PATHS = ( 525 | "$(inherited)", 526 | "$(PROJECT_DIR)/Flutter", 527 | ); 528 | PRODUCT_BUNDLE_IDENTIFIER = dev.com.jesway.example; 529 | PRODUCT_NAME = "$(TARGET_NAME)"; 530 | SWIFT_OBJC_BRIDGING_HEADER = "Runner-Bridging-Header.h"; 531 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 532 | SWIFT_VERSION = 5.0; 533 | VERSIONING_SYSTEM = "apple-generic"; 534 | }; 535 | name = Debug; 536 | }; 537 | 97C147071CF9000F007C117D /* Release */ = { 538 | isa = XCBuildConfiguration; 539 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 540 | buildSettings = { 541 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 542 | CLANG_ENABLE_MODULES = YES; 543 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 544 | ENABLE_BITCODE = NO; 545 | FRAMEWORK_SEARCH_PATHS = ( 546 | "$(inherited)", 547 | "$(PROJECT_DIR)/Flutter", 548 | ); 549 | INFOPLIST_FILE = Runner/Info.plist; 550 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 551 | LIBRARY_SEARCH_PATHS = ( 552 | "$(inherited)", 553 | "$(PROJECT_DIR)/Flutter", 554 | ); 555 | PRODUCT_BUNDLE_IDENTIFIER = dev.com.jesway.example; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | SWIFT_OBJC_BRIDGING_HEADER = "Runner-Bridging-Header.h"; 558 | SWIFT_VERSION = 5.0; 559 | VERSIONING_SYSTEM = "apple-generic"; 560 | }; 561 | name = Release; 562 | }; 563 | /* End XCBuildConfiguration section */ 564 | 565 | /* Begin XCConfigurationList section */ 566 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 567 | isa = XCConfigurationList; 568 | buildConfigurations = ( 569 | 97C147031CF9000F007C117D /* Debug */, 570 | 97C147041CF9000F007C117D /* Release */, 571 | 249021D3217E4FDB00AE95B9 /* Profile */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 577 | isa = XCConfigurationList; 578 | buildConfigurations = ( 579 | 97C147061CF9000F007C117D /* Debug */, 580 | 97C147071CF9000F007C117D /* Release */, 581 | 249021D4217E4FDB00AE95B9 /* Profile */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | defaultConfigurationName = Release; 585 | }; 586 | /* End XCConfigurationList section */ 587 | }; 588 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 589 | } 590 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_translate_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_localizations/flutter_localizations.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_translate/flutter_translate.dart'; 5 | 6 | void main() async 7 | { 8 | var delegate = await LocalizationDelegate.create( 9 | fallbackLocale: 'en_US', 10 | supportedLocales: ['en_US', 'es', 'fa', 'ar', 'ru']); 11 | 12 | runApp(LocalizedApp(delegate, MyApp())); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | 20 | var localizationDelegate = LocalizedApp.of(context).delegate; 21 | 22 | return LocalizationProvider( 23 | state: LocalizationProvider.of(context).state, 24 | child: MaterialApp( 25 | title: 'Flutter Translate Demo', 26 | localizationsDelegates: [ 27 | GlobalMaterialLocalizations.delegate, 28 | GlobalWidgetsLocalizations.delegate, 29 | localizationDelegate 30 | ], 31 | supportedLocales: localizationDelegate.supportedLocales, 32 | locale: localizationDelegate.currentLocale, 33 | theme: ThemeData(primarySwatch: Colors.blue), 34 | home: MyHomePage(), 35 | ), 36 | ); 37 | } 38 | } 39 | 40 | class MyHomePage extends StatefulWidget { 41 | MyHomePage({Key? key, this.title}) : super(key: key); 42 | final String? title; 43 | 44 | @override 45 | _MyHomePageState createState() => _MyHomePageState(); 46 | } 47 | 48 | class _MyHomePageState extends State { 49 | 50 | int _counter = 0; 51 | 52 | void _decrementCounter() => setState(() => _counter--); 53 | 54 | void _incrementCounter() => setState(() => _counter++); 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | var localizationDelegate = LocalizedApp.of(context).delegate; 59 | 60 | return Scaffold( 61 | appBar: AppBar( 62 | title: Text(translate('app_bar.title')), 63 | ), 64 | body: Center( 65 | child: Column( 66 | mainAxisAlignment: MainAxisAlignment.center, 67 | children: [ 68 | Text(translate('language.selected_message', args: {'language': translate('language.name.${localizationDelegate.currentLocale.languageCode}')})), 69 | Padding( 70 | padding: EdgeInsets.only(top: 25, bottom: 160), 71 | child: CupertinoButton.filled( 72 | child: Text(translate('button.change_language')), 73 | padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 36.0), 74 | onPressed: () => _onActionSheetPress(context), 75 | ) 76 | ), 77 | 78 | Padding(padding: const EdgeInsets.only(bottom: 10), 79 | child: Text(translatePlural('plural.demo', _counter)) 80 | ), 81 | Row( 82 | mainAxisAlignment: MainAxisAlignment.center, 83 | children: [ 84 | IconButton( 85 | icon: Icon(Icons.remove_circle), 86 | iconSize: 48, 87 | onPressed: _counter > 0 ? () => setState(() => _decrementCounter()) : null, 88 | ), 89 | IconButton( 90 | icon: Icon(Icons.add_circle), 91 | color: Colors.blue, 92 | iconSize: 48, 93 | onPressed: () => setState(() => _incrementCounter()), 94 | ), 95 | ], 96 | ) 97 | 98 | ], 99 | ), 100 | ), 101 | ); 102 | } 103 | 104 | void showDemoActionSheet({required BuildContext context, required Widget child}) { 105 | showCupertinoModalPopup( 106 | context: context, 107 | builder: (BuildContext context) => child).then((String? value) 108 | { 109 | if(value != null) 110 | changeLocale(context, value); 111 | }); 112 | } 113 | 114 | void _onActionSheetPress(BuildContext context) { 115 | showDemoActionSheet( 116 | context: context, 117 | child: CupertinoActionSheet( 118 | title: Text(translate('language.selection.title')), 119 | message: Text(translate('language.selection.message')), 120 | actions: [ 121 | CupertinoActionSheetAction( 122 | child: Text(translate('language.name.en')), 123 | onPressed: () => Navigator.pop(context, 'en_US'), 124 | ), 125 | CupertinoActionSheetAction( 126 | child: Text(translate('language.name.es')), 127 | onPressed: () => Navigator.pop(context, 'es'), 128 | ), 129 | CupertinoActionSheetAction( 130 | child: Text(translate('language.name.ar')), 131 | onPressed: () => Navigator.pop(context, 'ar'), 132 | ), 133 | CupertinoActionSheetAction( 134 | child: Text(translate('language.name.ru')), 135 | onPressed: () => Navigator.pop(context, 'ru'), 136 | ), 137 | ], 138 | cancelButton: CupertinoActionSheetAction( 139 | child: Text(translate('button.cancel')), 140 | isDefaultAction: true, 141 | onPressed: () => Navigator.pop(context, null), 142 | ), 143 | ), 144 | ); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: Example project for the flutter_translate library 3 | publish_to: none 4 | version: 4.1.0 5 | 6 | environment: 7 | sdk: '>=2.17.0 <4.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | flutter_localizations: 13 | sdk: flutter 14 | flutter_translate: 15 | path: ../ 16 | 17 | flutter: 18 | 19 | uses-material-design: true 20 | assets: 21 | - assets/i18n/ 22 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "minimal-ui", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(example LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "example") 5 | 6 | cmake_policy(SET CMP0063 NEW) 7 | 8 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 9 | 10 | # Configure build options. 11 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 12 | if(IS_MULTICONFIG) 13 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 14 | CACHE STRING "" FORCE) 15 | else() 16 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 17 | set(CMAKE_BUILD_TYPE "Debug" CACHE 18 | STRING "Flutter build mode" FORCE) 19 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 20 | "Debug" "Profile" "Release") 21 | endif() 22 | endif() 23 | 24 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 25 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 26 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 27 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 28 | 29 | # Use Unicode for all projects. 30 | add_definitions(-DUNICODE -D_UNICODE) 31 | 32 | # Compilation settings that should be applied to most targets. 33 | function(APPLY_STANDARD_SETTINGS TARGET) 34 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 35 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 36 | target_compile_options(${TARGET} PRIVATE /EHsc) 37 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 38 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 39 | endfunction() 40 | 41 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 42 | 43 | # Flutter library and tool build rules. 44 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 45 | 46 | # Application build 47 | add_subdirectory("runner") 48 | 49 | # Generated plugin build rules, which manage building the plugins and adding 50 | # them to the application. 51 | include(flutter/generated_plugins.cmake) 52 | 53 | 54 | # === Installation === 55 | # Support files are copied into place next to the executable, so that it can 56 | # run in place. This is done instead of making a separate bundle (as on Linux) 57 | # so that building and running from within Visual Studio will work. 58 | set(BUILD_BUNDLE_DIR "$") 59 | # Make the "install" step default, as it's required to run. 60 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 61 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 62 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 63 | endif() 64 | 65 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 66 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 67 | 68 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 69 | COMPONENT Runtime) 70 | 71 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 72 | COMPONENT Runtime) 73 | 74 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 75 | COMPONENT Runtime) 76 | 77 | if(PLUGIN_BUNDLED_LIBRARIES) 78 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 79 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 80 | COMPONENT Runtime) 81 | endif() 82 | 83 | # Fully re-copy the assets directory on each build to avoid having stale files 84 | # from a previous install. 85 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 86 | install(CODE " 87 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 88 | " COMPONENT Runtime) 89 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 90 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 91 | 92 | # Install the AOT library on non-Debug builds only. 93 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 94 | CONFIGURATIONS Profile;Release 95 | COMPONENT Runtime) 96 | -------------------------------------------------------------------------------- /example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 11 | 12 | # Set fallback configurations for older versions of the flutter tool. 13 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM) 14 | set(FLUTTER_TARGET_PLATFORM "windows-x64") 15 | endif() 16 | 17 | # === Flutter Library === 18 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 19 | 20 | # Published to parent scope for install step. 21 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 22 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 23 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 24 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 25 | 26 | list(APPEND FLUTTER_LIBRARY_HEADERS 27 | "flutter_export.h" 28 | "flutter_windows.h" 29 | "flutter_messenger.h" 30 | "flutter_plugin_registrar.h" 31 | "flutter_texture_registrar.h" 32 | ) 33 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 34 | add_library(flutter INTERFACE) 35 | target_include_directories(flutter INTERFACE 36 | "${EPHEMERAL_DIR}" 37 | ) 38 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 39 | add_dependencies(flutter flutter_assemble) 40 | 41 | # === Wrapper === 42 | list(APPEND CPP_WRAPPER_SOURCES_CORE 43 | "core_implementations.cc" 44 | "standard_codec.cc" 45 | ) 46 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 47 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 48 | "plugin_registrar.cc" 49 | ) 50 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 51 | list(APPEND CPP_WRAPPER_SOURCES_APP 52 | "flutter_engine.cc" 53 | "flutter_view_controller.cc" 54 | ) 55 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 56 | 57 | # Wrapper sources needed for a plugin. 58 | add_library(flutter_wrapper_plugin STATIC 59 | ${CPP_WRAPPER_SOURCES_CORE} 60 | ${CPP_WRAPPER_SOURCES_PLUGIN} 61 | ) 62 | apply_standard_settings(flutter_wrapper_plugin) 63 | set_target_properties(flutter_wrapper_plugin PROPERTIES 64 | POSITION_INDEPENDENT_CODE ON) 65 | set_target_properties(flutter_wrapper_plugin PROPERTIES 66 | CXX_VISIBILITY_PRESET hidden) 67 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 68 | target_include_directories(flutter_wrapper_plugin PUBLIC 69 | "${WRAPPER_ROOT}/include" 70 | ) 71 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 72 | 73 | # Wrapper sources needed for the runner. 74 | add_library(flutter_wrapper_app STATIC 75 | ${CPP_WRAPPER_SOURCES_CORE} 76 | ${CPP_WRAPPER_SOURCES_APP} 77 | ) 78 | apply_standard_settings(flutter_wrapper_app) 79 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 80 | target_include_directories(flutter_wrapper_app PUBLIC 81 | "${WRAPPER_ROOT}/include" 82 | ) 83 | add_dependencies(flutter_wrapper_app flutter_assemble) 84 | 85 | # === Flutter tool backend === 86 | # _phony_ is a non-existent file to force this command to run every time, 87 | # since currently there's no way to get a full input/output list from the 88 | # flutter tool. 89 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 90 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 91 | add_custom_command( 92 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 93 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 94 | ${CPP_WRAPPER_SOURCES_APP} 95 | ${PHONY_OUTPUT} 96 | COMMAND ${CMAKE_COMMAND} -E env 97 | ${FLUTTER_TOOL_ENVIRONMENT} 98 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 99 | ${FLUTTER_TARGET_PLATFORM} $ 100 | VERBATIM 101 | ) 102 | add_custom_target(flutter_assemble DEPENDS 103 | "${FLUTTER_LIBRARY}" 104 | ${FLUTTER_LIBRARY_HEADERS} 105 | ${CPP_WRAPPER_SOURCES_CORE} 106 | ${CPP_WRAPPER_SOURCES_PLUGIN} 107 | ${CPP_WRAPPER_SOURCES_APP} 108 | ) 109 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /example/windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(runner LANGUAGES CXX) 3 | 4 | add_executable(${BINARY_NAME} WIN32 5 | "flutter_window.cpp" 6 | "main.cpp" 7 | "run_loop.cpp" 8 | "utils.cpp" 9 | "win32_window.cpp" 10 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 11 | "Runner.rc" 12 | "runner.exe.manifest" 13 | ) 14 | apply_standard_settings(${BINARY_NAME}) 15 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 16 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 17 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 18 | add_dependencies(${BINARY_NAME} flutter_assemble) 19 | -------------------------------------------------------------------------------- /example/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "Jesway Labs" "\0" 93 | VALUE "FileDescription", "A new Flutter project." "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2021 Jesway Labs. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "example.exe" "\0" 98 | VALUE "ProductName", "example" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(RunLoop* run_loop, 8 | const flutter::DartProject& project) 9 | : run_loop_(run_loop), project_(project) {} 10 | 11 | FlutterWindow::~FlutterWindow() {} 12 | 13 | bool FlutterWindow::OnCreate() { 14 | if (!Win32Window::OnCreate()) { 15 | return false; 16 | } 17 | 18 | RECT frame = GetClientArea(); 19 | 20 | // The size here must match the window dimensions to avoid unnecessary surface 21 | // creation / destruction in the startup path. 22 | flutter_controller_ = std::make_unique( 23 | frame.right - frame.left, frame.bottom - frame.top, project_); 24 | // Ensure that basic setup of the controller was successful. 25 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 26 | return false; 27 | } 28 | RegisterPlugins(flutter_controller_->engine()); 29 | run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); 30 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 31 | return true; 32 | } 33 | 34 | void FlutterWindow::OnDestroy() { 35 | if (flutter_controller_) { 36 | run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); 37 | flutter_controller_ = nullptr; 38 | } 39 | 40 | Win32Window::OnDestroy(); 41 | } 42 | 43 | LRESULT 44 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 45 | WPARAM const wparam, 46 | LPARAM const lparam) noexcept { 47 | // Give Flutter, including plugins, an opportunity to handle window messages. 48 | if (flutter_controller_) { 49 | std::optional result = 50 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 51 | lparam); 52 | if (result) { 53 | return *result; 54 | } 55 | } 56 | 57 | switch (message) { 58 | case WM_FONTCHANGE: 59 | flutter_controller_->engine()->ReloadSystemFonts(); 60 | break; 61 | } 62 | 63 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 64 | } 65 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "run_loop.h" 10 | #include "win32_window.h" 11 | 12 | // A window that does nothing but host a Flutter view. 13 | class FlutterWindow : public Win32Window { 14 | public: 15 | // Creates a new FlutterWindow driven by the |run_loop|, hosting a 16 | // Flutter view running |project|. 17 | explicit FlutterWindow(RunLoop* run_loop, 18 | const flutter::DartProject& project); 19 | virtual ~FlutterWindow(); 20 | 21 | protected: 22 | // Win32Window: 23 | bool OnCreate() override; 24 | void OnDestroy() override; 25 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 26 | LPARAM const lparam) noexcept override; 27 | 28 | private: 29 | // The run loop driving events for this window. 30 | RunLoop* run_loop_; 31 | 32 | // The project to run. 33 | flutter::DartProject project_; 34 | 35 | // The Flutter instance hosted by this window. 36 | std::unique_ptr flutter_controller_; 37 | }; 38 | 39 | #endif // RUNNER_FLUTTER_WINDOW_H_ 40 | -------------------------------------------------------------------------------- /example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "run_loop.h" 7 | #include "utils.h" 8 | 9 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 10 | _In_ wchar_t *command_line, _In_ int show_command) { 11 | // Attach to console when present (e.g., 'flutter run') or create a 12 | // new console when running with a debugger. 13 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 14 | CreateAndAttachConsole(); 15 | } 16 | 17 | // Initialize COM, so that it is available for use in the library and/or 18 | // plugins. 19 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 20 | 21 | RunLoop run_loop; 22 | 23 | flutter::DartProject project(L"data"); 24 | 25 | std::vector command_line_arguments = 26 | GetCommandLineArguments(); 27 | 28 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 29 | 30 | FlutterWindow window(&run_loop, project); 31 | Win32Window::Point origin(10, 10); 32 | Win32Window::Size size(1280, 720); 33 | if (!window.CreateAndShow(L"example", origin, size)) { 34 | return EXIT_FAILURE; 35 | } 36 | window.SetQuitOnClose(true); 37 | 38 | run_loop.Run(); 39 | 40 | ::CoUninitialize(); 41 | return EXIT_SUCCESS; 42 | } 43 | -------------------------------------------------------------------------------- /example/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /example/windows/runner/run_loop.cpp: -------------------------------------------------------------------------------- 1 | #include "run_loop.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | RunLoop::RunLoop() {} 8 | 9 | RunLoop::~RunLoop() {} 10 | 11 | void RunLoop::Run() { 12 | bool keep_running = true; 13 | TimePoint next_flutter_event_time = TimePoint::clock::now(); 14 | while (keep_running) { 15 | std::chrono::nanoseconds wait_duration = 16 | std::max(std::chrono::nanoseconds(0), 17 | next_flutter_event_time - TimePoint::clock::now()); 18 | ::MsgWaitForMultipleObjects( 19 | 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), 20 | QS_ALLINPUT); 21 | bool processed_events = false; 22 | MSG message; 23 | // All pending Windows messages must be processed; MsgWaitForMultipleObjects 24 | // won't return again for items left in the queue after PeekMessage. 25 | while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { 26 | processed_events = true; 27 | if (message.message == WM_QUIT) { 28 | keep_running = false; 29 | break; 30 | } 31 | ::TranslateMessage(&message); 32 | ::DispatchMessage(&message); 33 | // Allow Flutter to process messages each time a Windows message is 34 | // processed, to prevent starvation. 35 | next_flutter_event_time = 36 | std::min(next_flutter_event_time, ProcessFlutterMessages()); 37 | } 38 | // If the PeekMessage loop didn't run, process Flutter messages. 39 | if (!processed_events) { 40 | next_flutter_event_time = 41 | std::min(next_flutter_event_time, ProcessFlutterMessages()); 42 | } 43 | } 44 | } 45 | 46 | void RunLoop::RegisterFlutterInstance( 47 | flutter::FlutterEngine* flutter_instance) { 48 | flutter_instances_.insert(flutter_instance); 49 | } 50 | 51 | void RunLoop::UnregisterFlutterInstance( 52 | flutter::FlutterEngine* flutter_instance) { 53 | flutter_instances_.erase(flutter_instance); 54 | } 55 | 56 | RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { 57 | TimePoint next_event_time = TimePoint::max(); 58 | for (auto instance : flutter_instances_) { 59 | std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); 60 | if (wait_duration != std::chrono::nanoseconds::max()) { 61 | next_event_time = 62 | std::min(next_event_time, TimePoint::clock::now() + wait_duration); 63 | } 64 | } 65 | return next_event_time; 66 | } 67 | -------------------------------------------------------------------------------- /example/windows/runner/run_loop.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_RUN_LOOP_H_ 2 | #define RUNNER_RUN_LOOP_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | // A runloop that will service events for Flutter instances as well 10 | // as native messages. 11 | class RunLoop { 12 | public: 13 | RunLoop(); 14 | ~RunLoop(); 15 | 16 | // Prevent copying 17 | RunLoop(RunLoop const&) = delete; 18 | RunLoop& operator=(RunLoop const&) = delete; 19 | 20 | // Runs the run loop until the application quits. 21 | void Run(); 22 | 23 | // Registers the given Flutter instance for event servicing. 24 | void RegisterFlutterInstance( 25 | flutter::FlutterEngine* flutter_instance); 26 | 27 | // Unregisters the given Flutter instance from event servicing. 28 | void UnregisterFlutterInstance( 29 | flutter::FlutterEngine* flutter_instance); 30 | 31 | private: 32 | using TimePoint = std::chrono::steady_clock::time_point; 33 | 34 | // Processes all currently pending messages for registered Flutter instances. 35 | TimePoint ProcessFlutterMessages(); 36 | 37 | std::set flutter_instances_; 38 | }; 39 | 40 | #endif // RUNNER_RUN_LOOP_H_ 41 | -------------------------------------------------------------------------------- /example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | if (target_length == 0) { 52 | return std::string(); 53 | } 54 | std::string utf8_string; 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.cpp: -------------------------------------------------------------------------------- 1 | #include "win32_window.h" 2 | 3 | #include 4 | 5 | #include "resource.h" 6 | 7 | namespace { 8 | 9 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; 10 | 11 | // The number of Win32Window objects that currently exist. 12 | static int g_active_window_count = 0; 13 | 14 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); 15 | 16 | // Scale helper to convert logical scaler values to physical using passed in 17 | // scale factor 18 | int Scale(int source, double scale_factor) { 19 | return static_cast(source * scale_factor); 20 | } 21 | 22 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. 23 | // This API is only needed for PerMonitor V1 awareness mode. 24 | void EnableFullDpiSupportIfAvailable(HWND hwnd) { 25 | HMODULE user32_module = LoadLibraryA("User32.dll"); 26 | if (!user32_module) { 27 | return; 28 | } 29 | auto enable_non_client_dpi_scaling = 30 | reinterpret_cast( 31 | GetProcAddress(user32_module, "EnableNonClientDpiScaling")); 32 | if (enable_non_client_dpi_scaling != nullptr) { 33 | enable_non_client_dpi_scaling(hwnd); 34 | FreeLibrary(user32_module); 35 | } 36 | } 37 | 38 | } // namespace 39 | 40 | // Manages the Win32Window's window class registration. 41 | class WindowClassRegistrar { 42 | public: 43 | ~WindowClassRegistrar() = default; 44 | 45 | // Returns the singleton registar instance. 46 | static WindowClassRegistrar* GetInstance() { 47 | if (!instance_) { 48 | instance_ = new WindowClassRegistrar(); 49 | } 50 | return instance_; 51 | } 52 | 53 | // Returns the name of the window class, registering the class if it hasn't 54 | // previously been registered. 55 | const wchar_t* GetWindowClass(); 56 | 57 | // Unregisters the window class. Should only be called if there are no 58 | // instances of the window. 59 | void UnregisterWindowClass(); 60 | 61 | private: 62 | WindowClassRegistrar() = default; 63 | 64 | static WindowClassRegistrar* instance_; 65 | 66 | bool class_registered_ = false; 67 | }; 68 | 69 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; 70 | 71 | const wchar_t* WindowClassRegistrar::GetWindowClass() { 72 | if (!class_registered_) { 73 | WNDCLASS window_class{}; 74 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); 75 | window_class.lpszClassName = kWindowClassName; 76 | window_class.style = CS_HREDRAW | CS_VREDRAW; 77 | window_class.cbClsExtra = 0; 78 | window_class.cbWndExtra = 0; 79 | window_class.hInstance = GetModuleHandle(nullptr); 80 | window_class.hIcon = 81 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); 82 | window_class.hbrBackground = 0; 83 | window_class.lpszMenuName = nullptr; 84 | window_class.lpfnWndProc = Win32Window::WndProc; 85 | RegisterClass(&window_class); 86 | class_registered_ = true; 87 | } 88 | return kWindowClassName; 89 | } 90 | 91 | void WindowClassRegistrar::UnregisterWindowClass() { 92 | UnregisterClass(kWindowClassName, nullptr); 93 | class_registered_ = false; 94 | } 95 | 96 | Win32Window::Win32Window() { 97 | ++g_active_window_count; 98 | } 99 | 100 | Win32Window::~Win32Window() { 101 | --g_active_window_count; 102 | Destroy(); 103 | } 104 | 105 | bool Win32Window::CreateAndShow(const std::wstring& title, 106 | const Point& origin, 107 | const Size& size) { 108 | Destroy(); 109 | 110 | const wchar_t* window_class = 111 | WindowClassRegistrar::GetInstance()->GetWindowClass(); 112 | 113 | const POINT target_point = {static_cast(origin.x), 114 | static_cast(origin.y)}; 115 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); 116 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); 117 | double scale_factor = dpi / 96.0; 118 | 119 | HWND window = CreateWindow( 120 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 121 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), 122 | Scale(size.width, scale_factor), Scale(size.height, scale_factor), 123 | nullptr, nullptr, GetModuleHandle(nullptr), this); 124 | 125 | if (!window) { 126 | return false; 127 | } 128 | 129 | return OnCreate(); 130 | } 131 | 132 | // static 133 | LRESULT CALLBACK Win32Window::WndProc(HWND const window, 134 | UINT const message, 135 | WPARAM const wparam, 136 | LPARAM const lparam) noexcept { 137 | if (message == WM_NCCREATE) { 138 | auto window_struct = reinterpret_cast(lparam); 139 | SetWindowLongPtr(window, GWLP_USERDATA, 140 | reinterpret_cast(window_struct->lpCreateParams)); 141 | 142 | auto that = static_cast(window_struct->lpCreateParams); 143 | EnableFullDpiSupportIfAvailable(window); 144 | that->window_handle_ = window; 145 | } else if (Win32Window* that = GetThisFromHandle(window)) { 146 | return that->MessageHandler(window, message, wparam, lparam); 147 | } 148 | 149 | return DefWindowProc(window, message, wparam, lparam); 150 | } 151 | 152 | LRESULT 153 | Win32Window::MessageHandler(HWND hwnd, 154 | UINT const message, 155 | WPARAM const wparam, 156 | LPARAM const lparam) noexcept { 157 | switch (message) { 158 | case WM_DESTROY: 159 | window_handle_ = nullptr; 160 | Destroy(); 161 | if (quit_on_close_) { 162 | PostQuitMessage(0); 163 | } 164 | return 0; 165 | 166 | case WM_DPICHANGED: { 167 | auto newRectSize = reinterpret_cast(lparam); 168 | LONG newWidth = newRectSize->right - newRectSize->left; 169 | LONG newHeight = newRectSize->bottom - newRectSize->top; 170 | 171 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, 172 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE); 173 | 174 | return 0; 175 | } 176 | case WM_SIZE: { 177 | RECT rect = GetClientArea(); 178 | if (child_content_ != nullptr) { 179 | // Size and position the child window. 180 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, 181 | rect.bottom - rect.top, TRUE); 182 | } 183 | return 0; 184 | } 185 | 186 | case WM_ACTIVATE: 187 | if (child_content_ != nullptr) { 188 | SetFocus(child_content_); 189 | } 190 | return 0; 191 | } 192 | 193 | return DefWindowProc(window_handle_, message, wparam, lparam); 194 | } 195 | 196 | void Win32Window::Destroy() { 197 | OnDestroy(); 198 | 199 | if (window_handle_) { 200 | DestroyWindow(window_handle_); 201 | window_handle_ = nullptr; 202 | } 203 | if (g_active_window_count == 0) { 204 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); 205 | } 206 | } 207 | 208 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { 209 | return reinterpret_cast( 210 | GetWindowLongPtr(window, GWLP_USERDATA)); 211 | } 212 | 213 | void Win32Window::SetChildContent(HWND content) { 214 | child_content_ = content; 215 | SetParent(content, window_handle_); 216 | RECT frame = GetClientArea(); 217 | 218 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left, 219 | frame.bottom - frame.top, true); 220 | 221 | SetFocus(child_content_); 222 | } 223 | 224 | RECT Win32Window::GetClientArea() { 225 | RECT frame; 226 | GetClientRect(window_handle_, &frame); 227 | return frame; 228 | } 229 | 230 | HWND Win32Window::GetHandle() { 231 | return window_handle_; 232 | } 233 | 234 | void Win32Window::SetQuitOnClose(bool quit_on_close) { 235 | quit_on_close_ = quit_on_close; 236 | } 237 | 238 | bool Win32Window::OnCreate() { 239 | // No-op; provided for subclasses. 240 | return true; 241 | } 242 | 243 | void Win32Window::OnDestroy() { 244 | // No-op; provided for subclasses. 245 | } 246 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | -------------------------------------------------------------------------------- /lib/flutter_translate.dart: -------------------------------------------------------------------------------- 1 | library flutter_translate; 2 | 3 | export 'src/utils/utils.dart'; 4 | export 'src/services/localization.dart'; 5 | export 'src/delegates/localization_delegate.dart'; 6 | export 'src/widgets/localization_provider.dart'; 7 | export 'src/widgets/localized_app.dart'; 8 | export 'src/widgets/localized_app_state.dart'; 9 | export 'src/interfaces/translate_preferences.dart'; 10 | export 'src/utils/device_locale.dart'; -------------------------------------------------------------------------------- /lib/src/constants/constants.dart: -------------------------------------------------------------------------------- 1 | class Constants 2 | { 3 | static const String assetManifestFilename = 'AssetManifest.json'; 4 | 5 | static const String localizedAssetsPath = 'assets/i18n'; 6 | 7 | static const String pluralZero = 'zero'; 8 | static const String pluralOne = 'one'; 9 | static const String pluralTwo = 'two'; 10 | static const String pluralFew = 'few'; 11 | static const String pluralMany = 'many'; 12 | static const String pluralOther = 'other'; 13 | 14 | static const String pluralValueArg = '{{value}}'; 15 | } -------------------------------------------------------------------------------- /lib/src/delegates/localization_delegate.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:intl/intl.dart'; 3 | import 'package:flutter_translate/flutter_translate.dart'; 4 | import 'package:flutter_translate/src/constants/constants.dart'; 5 | import 'package:flutter_translate/src/services/locale_service.dart'; 6 | import 'package:flutter_translate/src/validators/configuration_validator.dart'; 7 | 8 | class LocalizationDelegate extends LocalizationsDelegate 9 | { 10 | Locale? _currentLocale; 11 | 12 | final Locale fallbackLocale; 13 | 14 | final List supportedLocales; 15 | 16 | final Map supportedLocalesMap; 17 | 18 | final ITranslatePreferences? preferences; 19 | 20 | LocaleChangedCallback? onLocaleChanged; 21 | 22 | Locale get currentLocale => _currentLocale!; 23 | 24 | LocalizationDelegate._(this.fallbackLocale, this.supportedLocales, this.supportedLocalesMap, this.preferences); 25 | 26 | Future changeLocale(Locale newLocale) async 27 | { 28 | var isInitializing = _currentLocale == null; 29 | 30 | var locale = LocaleService.findLocale(newLocale, supportedLocales) ?? fallbackLocale; 31 | 32 | if(_currentLocale == locale) return; 33 | 34 | var localizedContent = await LocaleService.getLocaleContent(locale, supportedLocalesMap); 35 | 36 | Localization.load(localizedContent); 37 | 38 | _currentLocale = locale; 39 | 40 | Intl.defaultLocale = _currentLocale?.languageCode; 41 | 42 | if(onLocaleChanged != null) 43 | { 44 | await onLocaleChanged!(locale); 45 | } 46 | 47 | if(!isInitializing && preferences != null) 48 | { 49 | await preferences!.savePreferredLocale(locale); 50 | } 51 | } 52 | 53 | @override 54 | Future load(Locale newLocale) async 55 | { 56 | if(currentLocale != newLocale) 57 | { 58 | await changeLocale(newLocale); 59 | } 60 | 61 | return Localization.instance; 62 | } 63 | 64 | 65 | @override 66 | bool isSupported(Locale? locale) => locale != null; 67 | 68 | @override 69 | bool shouldReload(LocalizationsDelegate old) => true; 70 | 71 | static Future create({ 72 | required String fallbackLocale, 73 | required List supportedLocales, 74 | String basePath = Constants.localizedAssetsPath, 75 | ITranslatePreferences? preferences}) async 76 | { 77 | WidgetsFlutterBinding.ensureInitialized(); 78 | 79 | var fallback = localeFromString(fallbackLocale); 80 | var localesMap = await LocaleService.getLocalesMap(supportedLocales, basePath); 81 | var locales = localesMap.keys.toList(); 82 | 83 | ConfigurationValidator.validate(fallback, locales); 84 | 85 | var delegate = LocalizationDelegate._(fallback, locales, localesMap, preferences); 86 | 87 | if(!await delegate._loadPreferences()) 88 | { 89 | await delegate._loadDeviceLocale(); 90 | } 91 | 92 | return delegate; 93 | } 94 | 95 | Future _loadPreferences() async 96 | { 97 | if(preferences == null) return false; 98 | 99 | Locale? locale; 100 | 101 | try 102 | { 103 | locale = await preferences!.getPreferredLocale(); 104 | } 105 | catch(e) 106 | { 107 | return false; 108 | } 109 | 110 | if(locale != null) 111 | { 112 | await changeLocale(locale); 113 | return true; 114 | } 115 | 116 | return false; 117 | } 118 | 119 | Future _loadDeviceLocale() async 120 | { 121 | try 122 | { 123 | var locale = getCurrentLocale(); 124 | 125 | if(locale != null) 126 | { 127 | await changeLocale(locale); 128 | } 129 | } 130 | catch(e) 131 | { 132 | await changeLocale(fallbackLocale); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib/src/interfaces/translate_preferences.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | abstract class ITranslatePreferences 4 | { 5 | Future savePreferredLocale(Locale locale); 6 | 7 | Future getPreferredLocale(); 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/services/locale_file_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter_translate/src/constants/constants.dart'; 4 | 5 | class LocaleFileService 6 | { 7 | static Future> getLocaleFiles(List locales, String basePath) async 8 | { 9 | var localizedFiles = await _getAllLocaleFiles(basePath); 10 | 11 | final files = new Map(); 12 | 13 | for(final language in locales.toSet()) 14 | { 15 | var file = _findLocaleFile(language, localizedFiles, basePath); 16 | 17 | files[language] = file; 18 | } 19 | 20 | return files; 21 | } 22 | 23 | static Future getLocaleContent(String file) async 24 | { 25 | final ByteData? data = await rootBundle.load(file); 26 | 27 | if (data == null) return null; 28 | 29 | return utf8.decode(data.buffer.asUint8List()); 30 | } 31 | 32 | static Future> _getAllLocaleFiles(String basePath) async 33 | { 34 | final manifest = await rootBundle.loadString(Constants.assetManifestFilename); 35 | 36 | Map map = jsonDecode(manifest); 37 | 38 | var separator = basePath.endsWith('/') ? '' : '/'; 39 | 40 | return map.keys.where((x) => x.startsWith('$basePath$separator')).toList(); 41 | } 42 | 43 | static String _findLocaleFile(String languageCode, List localizedFiles, String basePath) 44 | { 45 | var file = _getFilepath(languageCode, basePath); 46 | 47 | if(!localizedFiles.contains(file)) 48 | { 49 | if(languageCode.contains('_')) 50 | { 51 | file = _getFilepath(languageCode.split('_').first, basePath); 52 | } 53 | } 54 | 55 | if(file == null) 56 | { 57 | throw new Exception('The asset file for the language "$languageCode" was not found.'); 58 | } 59 | 60 | return file; 61 | } 62 | 63 | static String? _getFilepath(String languageCode, String basePath) 64 | { 65 | var separator = basePath.endsWith('/') ? '' : '/'; 66 | 67 | return '$basePath$separator$languageCode.json'; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/src/services/locale_service.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:ui'; 3 | import 'package:flutter_translate/flutter_translate.dart'; 4 | 5 | import 'locale_file_service.dart'; 6 | 7 | class LocaleService 8 | { 9 | static Future> getLocalesMap(List locales, String basePath) async 10 | { 11 | var files = await LocaleFileService.getLocaleFiles(locales, basePath); 12 | 13 | return files.map((x,y) => MapEntry(localeFromString(x), y)); 14 | } 15 | 16 | static Locale? findLocale(Locale locale, List supportedLocales) 17 | { 18 | // Not supported by all null safety versions 19 | Locale? existing; // = supportedLocales.firstWhereOrNull((x) => x == locale); 20 | 21 | for (var x in supportedLocales) 22 | { 23 | if (x == locale) 24 | { 25 | existing = x; 26 | break; 27 | } 28 | } 29 | 30 | if(existing == null) 31 | { 32 | // Not supported by all null safety versions 33 | // existing = supportedLocales.firstWhereOrNull((x) => x.languageCode == locale.languageCode); 34 | for (var x in supportedLocales) 35 | { 36 | if (x.languageCode == locale.languageCode) 37 | { 38 | existing = x; 39 | break; 40 | } 41 | } 42 | 43 | } 44 | 45 | return existing; 46 | } 47 | 48 | static Future> getLocaleContent(Locale locale, Map supportedLocales) async 49 | { 50 | var file = supportedLocales[locale]; 51 | 52 | if (file == null) return {}; 53 | 54 | var content = await LocaleFileService.getLocaleContent(file); 55 | 56 | if (content == null) return {}; 57 | 58 | return json.decode(content); 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lib/src/services/localization.dart: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter_translate/src/constants/constants.dart'; 3 | import 'package:intl/intl.dart'; 4 | 5 | class Localization 6 | { 7 | late Map _translations; 8 | 9 | Localization._(); 10 | 11 | static Localization? _instance; 12 | static Localization get instance => _instance ?? (_instance = Localization._()); 13 | 14 | static void load(Map translations) 15 | { 16 | instance._translations = translations; 17 | } 18 | 19 | String translate(String key, {Map? args}) 20 | { 21 | var translation = _getTranslation(key, _translations); 22 | 23 | if (translation != null && args != null) 24 | { 25 | translation = _assignArguments(translation, args); 26 | } 27 | 28 | return translation ?? key; 29 | } 30 | 31 | String plural(String key, num value, {Map? args}) 32 | { 33 | final forms = _getAllPluralForms(key, _translations); 34 | 35 | return Intl.plural( 36 | value, 37 | zero: _putArgs(forms[Constants.pluralZero], value, args: args), 38 | one: _putArgs(forms[Constants.pluralOne], value, args: args), 39 | two: _putArgs(forms[Constants.pluralTwo], value, args: args), 40 | few: _putArgs(forms[Constants.pluralFew], value, args: args), 41 | many: _putArgs(forms[Constants.pluralMany], value, args: args), 42 | other: _putArgs(forms[Constants.pluralOther], value, args: args) ?? '$key.${Constants.pluralOther}', 43 | ); 44 | } 45 | 46 | String? _putArgs(String? template, num value, {Map? args}) 47 | { 48 | if (template == null) 49 | { 50 | return null; 51 | } 52 | 53 | template = template.replaceAll(Constants.pluralValueArg, value.toString()); 54 | 55 | if (args == null) 56 | { 57 | return template; 58 | } 59 | 60 | for (String k in args.keys) 61 | { 62 | template = template!.replaceAll("{$k}", args[k].toString()); 63 | } 64 | 65 | return template; 66 | } 67 | 68 | String _assignArguments(String value, Map args) 69 | { 70 | for(final key in args.keys) 71 | { 72 | value = value.replaceAll('{$key}', '${args[key]}'); 73 | } 74 | 75 | return value; 76 | } 77 | 78 | String? _getTranslation(String key, Map map) 79 | { 80 | List keys = key.split('.'); 81 | 82 | if (keys.length > 1) 83 | { 84 | var firstKey = keys.first; 85 | 86 | if(map.containsKey(firstKey) && map[firstKey] is! String) 87 | { 88 | return _getTranslation(key.substring(key.indexOf('.') + 1), map[firstKey]); 89 | } 90 | } 91 | 92 | return map[key]; 93 | } 94 | 95 | Map _getAllPluralForms(String key, Map map) 96 | { 97 | List keys = key.split('.'); 98 | 99 | if (keys.length > 1) 100 | { 101 | var firstKey = keys.first; 102 | 103 | if (map.containsKey(firstKey) && map[firstKey] is! String) 104 | { 105 | return _getAllPluralForms(key.substring(key.indexOf('.') + 1), map[firstKey]); 106 | } 107 | } 108 | 109 | final result = {}; 110 | 111 | for (String k in map[key].keys) 112 | { 113 | result[k] = map[key][k].toString(); 114 | } 115 | 116 | return result; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /lib/src/services/localization_configuration.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_translate/flutter_translate.dart'; 3 | import 'package:flutter_translate/src/constants/constants.dart'; 4 | import 'locale_file_service.dart'; 5 | 6 | class LocalizationConfiguration 7 | { 8 | Map? _localizations; 9 | 10 | Map? get localizations => _localizations; 11 | 12 | final Locale fallbackLocale; 13 | 14 | final List supportedLocales; 15 | 16 | LocalizationConfiguration._(this.fallbackLocale, this.supportedLocales); 17 | 18 | static Future create(String fallbackLanguage, List supportedLanguages, {String basePath = Constants.localizedAssetsPath}) async 19 | { 20 | var configuration = new LocalizationConfiguration._(localeFromString(fallbackLanguage), _generateSupportedLocales(supportedLanguages)); 21 | 22 | _validateConfiguration(fallbackLanguage, supportedLanguages); 23 | 24 | var files = await LocaleFileService.getLocaleFiles(supportedLanguages, basePath); 25 | 26 | configuration._localizations = files.map((x,y) => _getLocalizedEntry(x, y)); 27 | 28 | return configuration; 29 | } 30 | 31 | static void _validateConfiguration(String fallbackLanguage, List supportedLanguages) 32 | { 33 | if(!supportedLanguages.contains(fallbackLanguage)) 34 | { 35 | throw new Exception('The fallbackLanguage [$fallbackLanguage] must be present in the supportedLanguages list [${supportedLanguages.join(", ")}].'); 36 | } 37 | } 38 | 39 | static List _generateSupportedLocales(List supportedLanguages) 40 | { 41 | return supportedLanguages.map((x) => localeFromString(x, languageCodeOnly: true)).toSet().toList(); 42 | } 43 | 44 | static MapEntry _getLocalizedEntry(String languageCode, String file) 45 | { 46 | Locale locale; 47 | 48 | if(languageCode.contains('_')) 49 | { 50 | var parts = languageCode.split('_'); 51 | 52 | locale = new Locale(parts[0], parts[1]); 53 | } 54 | else 55 | { 56 | locale = new Locale(languageCode); 57 | } 58 | 59 | return MapEntry(locale, file); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/utils/device_locale.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:universal_io/io.dart'; 3 | 4 | /// Returns the current device locale 5 | Locale? getCurrentLocale() 6 | { 7 | return _localeFromString(Platform.localeName); 8 | } 9 | 10 | Locale? _localeFromString(String code) 11 | { 12 | var separator = code.contains('_') ? '_' : code.contains('-') ? '-' : null; 13 | 14 | if (separator != null) 15 | { 16 | var parts = code.split(RegExp(separator)); 17 | 18 | return Locale(parts[0], parts[1]); 19 | } 20 | else 21 | { 22 | return Locale(code); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/utils/utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_translate/flutter_translate.dart'; 3 | 4 | typedef LocaleChangedCallback = Future Function(Locale locale); 5 | 6 | Locale localeFromString(String code, {bool languageCodeOnly = false}) 7 | { 8 | if (code.contains('_')) 9 | { 10 | var parts = code.split('_'); 11 | 12 | return languageCodeOnly ? Locale(parts[0]) : Locale(parts[0], parts[1]); 13 | } 14 | else 15 | { 16 | return Locale(code); 17 | } 18 | } 19 | 20 | String localeToString(Locale locale) 21 | { 22 | return locale.countryCode != null ? '${locale.languageCode}_${locale.countryCode}' : locale.languageCode; 23 | } 24 | 25 | /// Translate the selected key into the currently selected locale 26 | String translate(String key, {Map? args}) 27 | { 28 | return Localization.instance.translate(key, args: args); 29 | } 30 | 31 | /// Translate the selected key into the currently selected locale using pluralization 32 | String translatePlural(String key, num value, {Map? args}) 33 | { 34 | return Localization.instance.plural(key, value, args: args); 35 | } 36 | 37 | /// Change the currently selected locale 38 | Future changeLocale(BuildContext context, String? localeCode) async 39 | { 40 | if (localeCode != null) 41 | { 42 | await LocalizedApp.of(context).delegate.changeLocale(localeFromString(localeCode)); 43 | 44 | LocalizationProvider.of(context).state.onLocaleChanged(); 45 | } 46 | } -------------------------------------------------------------------------------- /lib/src/validators/configuration_validator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | class ConfigurationValidator 4 | { 5 | static void validate(Locale fallbackLocale, List supportedLocales) 6 | { 7 | if(!supportedLocales.contains(fallbackLocale)) 8 | { 9 | throw new Exception('The locale [$fallbackLocale] must be present in the list of supported locales [${supportedLocales.join(", ")}].'); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/widgets/localization_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_translate/flutter_translate.dart'; 3 | 4 | class LocalizationProvider extends InheritedWidget 5 | { 6 | final LocalizedAppState state; 7 | 8 | final Widget child; 9 | 10 | LocalizationProvider({Key? key, required this.child, required this.state}) : super(key: key, child: child); 11 | 12 | static LocalizationProvider of(BuildContext context) => (context.dependOnInheritedWidgetOfExactType())!; 13 | 14 | @override 15 | bool updateShouldNotify(LocalizationProvider oldWidget) => true; 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/widgets/localized_app.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_translate/flutter_translate.dart'; 3 | 4 | class LocalizedApp extends StatefulWidget 5 | { 6 | final Widget child; 7 | 8 | final LocalizationDelegate delegate; 9 | 10 | LocalizedApp(this.delegate, this.child); 11 | 12 | LocalizedAppState createState() => LocalizedAppState(); 13 | 14 | static LocalizedApp of(BuildContext context) => context.findAncestorWidgetOfExactType()!; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/widgets/localized_app_state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'localized_app.dart'; 3 | import 'localization_provider.dart'; 4 | 5 | class LocalizedAppState extends State 6 | { 7 | void onLocaleChanged() => setState(() {}); 8 | 9 | @override 10 | Widget build(BuildContext context) => LocalizationProvider(state: this, child: widget.child); 11 | } 12 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_translate 2 | description: Flutter Translate is a fully featured localization / internationalization (i18n) library for Flutter. 3 | version: 4.1.0 4 | homepage: https://jesway.com 5 | repository: https://github.com/Jesway/flutter_translate 6 | 7 | environment: 8 | sdk: '>=2.17.0 <4.0.0' 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | universal_io: ^2.2.2 14 | intl: ^0.19.0 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | flutter: -------------------------------------------------------------------------------- /resources/gifs/flutter_translate_screen.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/resources/gifs/flutter_translate_screen.gif -------------------------------------------------------------------------------- /resources/images/flutter_translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jesway/flutter_translate/c4e46902ecf15a2746e3ed07f2a7c5ecf1b8b833/resources/images/flutter_translate.png --------------------------------------------------------------------------------