Popular posts
-
使用 acme.sh 来生成免费的证书
推荐使用 root 用户来安装和操作!!!
操作步骤
安装 acme.sh
运行以下命令安装 acme.sh:
curl https://get.acme.sh | sh -s email=my@example.com
然后,加载环境变量:
source ~/.bashrc
使用 Cloudflare 的 DNS 来签发证书
配置 Cloudflare API 令牌和邮箱:
export CF_Token="你的API令牌"
export CF_Email="你的邮箱"
执行一下命令:
acme.sh --issue --dns dns_cf -d example.com -d *.example.com
安装证书
acme.sh --install-cert -d example.com \ --key-file /etc/nginx/ssl/example.com.key \ --fullchain-file /etc/nginx/ssl/fullchain.cer \ --reloadcmd "systemctl reload nginx"
查看已安装证书信息
acme.sh --info -d example.com
nginx 配置
- 静态文件代理
server { listen 443 ssl; server_name example.com; ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers HIGH:!aNULL:!MD5; root /data/projects/your-website; index index.html; location / { try_files $uri $uri/ =404; } }
- 反向代理
server { listen 80; server_name sub.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name sub.example.com; ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://127.0.0.1:8075; } }
-
Flutter里的国际化,简言之,分为两大步:
- 创建本地化资源。
- 创建本地化资源代理,并配置到APP入口函数。
应用内切换语言,关键点有两个:
- 指定应用的语言:设置 MaterialApp 的 locate 参数。
- 取得当前语言对应的本地化资源文件:
Localizations.of<S>(context, S)
。
Localizations 继承自 StatefulWidget ,内部属性 locale 有变化,child 就会重建。
以下,为国际化代码的具体实现:
前提
在
pubspec.yaml
文件中添加它和 intl作为依赖flutter pub add flutter_localizations --sdk=flutter flutter pub add intl:any
最终的
pubspec.yaml
文件中形如:dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter intl: any
1. 创建本地化资源
1.1 创建本地化资源接口,声明需要翻译的字段。
使用接口定义待翻译字段的好处是:实现类/子类 必须对抽象字段进行赋值,否则编译器会报错。 相比之下,字典的方式,某个 key 没有赋值,编译器检查不出来,而且,哪些 key 是有用的,哪些 key 没用了,也不好确定。
/// 本地化资源 基类 abstract class S { /// 本地化资源代理对象 static const LocalizationsDelegate delegate = ProjectLocalizationsDelegate(); /// 根据上下文中的 [Locale] 取得对应的本地化资源。 static S of(BuildContext context) { return Localizations.of<S>(context, S)!; } /// 支持的语言。 /// 如果本地没有保存的语言配置参数,APP会默认使用第一个作为默认语言。 static List<Locale> supportedLocales = [ const Locale('en'), const Locale('ja'), const Locale('zh') ]; // 不需要翻译的字段,直接赋值。 static String appName = 'AppName'; static String english = 'English'; static String japanese = '日本語'; static String simpleChinese = '简体中文'; static Map<String, String> localeSets = { 'en': english, 'ja': japanese, 'zh': simpleChinese }; // 需要翻译的字段追加到下面,在子类中进行赋值。 String get cancel; String get ok; String get readAndAgree; String get privacyPolicy; String get termsOfService; String get me; String get settingsLanguage; }
1.2 创建指定语言的资源类(实现上一步中的接口),对接口中的成员变量进行赋值。
/// 英文 class ProjectLocalizationsEN implements S { @override String get cancel => "Cancel"; @override String get ok => "OK"; } /// 中文 class ProjectLocalizationsZH implements S { @override String get cancel => "取消"; @override String get ok => "确定"; } /// 日文 class ProjectLocalizationsJA implements S { @override String get cancel => "キャンセル"; @override String get ok => "確定"; }
2. 创建本地化资源代理
2.1 创建本地化资源代理类(继承 LocalizationsDelegate),重写 load 方法,根据 locale 返回对应语言的资源。
/// 项目本地化资源代理 class ProjectLocalizationsDelegate extends LocalizationsDelegate<S> { const ProjectLocalizationsDelegate(); @override bool isSupported(Locale locale) => true; @override Future<S> load(Locale locale) { return SynchronousFuture<S>(getMaterialTranslation(locale)); } @override bool shouldReload(ProjectLocalizationsDelegate old) => false; /// 根据 locale 得到对应的本地化资源 S getMaterialTranslation(Locale locale) { switch (locale.languageCode) { case 'en': return ProjectLocalizationsEN(); case 'zh': return ProjectLocalizationsZH(); case 'ja': return ProjectLocalizationsJA(); default: return ProjectLocalizationsEN(); } } }
2.2 在程序入口 MaterialApp 中的 localizationsDelegates 参数中,加入自己创建的本地化资源代理类。
import 'package:flutter_localizations/flutter_localizations.dart'; class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Consumer<LocaleStore>(builder: (context, localeStore, _) { return OKToast( movingOnWindowChange: false, child: MaterialApp( onGenerateTitle: (context) => S.appName, // 不需要翻译的字段,可以直接类名调用。 theme: AppTheme.lightTheme(context), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, // 项目本地化资源代理 S.delegate, ], // 支持的语言 supportedLocales: S.supportedLocales, // 指定语言,如果 localStore 里没有保存的语言参数,则直接使用 S 文件中配置的第一个语言。 locale: localeStore.languageCode == null ? S.supportedLocales.first : Locale(localeStore.languageCode!), routes: RouteMap.routes, home: const HomePage(), builder: (context, child) => GestureDetector( onTap: () => CommonUtils.hideKeyboard(context), child: child, ), ), ); }); } }
配置完成,开始使用:
- 不需要翻译的字段,使用方式:
S.appName
- 支持多语言的字段,使用方式:
S.of(context).ok
S.of(context). cancel
-
-
将
google() mavenCentral()
修改为:
maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/central' }
替换过期jcenter地址:
maven { url 'https://maven.aliyun.com/repository/jcenter' }
-
M1 平台 pod install 出错
- 方法1:命令前加 arch -x86_64
pod install
或者pod update
前面加arch -x86_64
如:
arch -x86_64 pod install
arch -x86_64 pod update
- 方法2: 卸载 cocoapods,用 brew 重新安装 cocoapods
gem list --local | grep cocoapods | awk '{print $1}' | xargs sudo gem uninstall
brew install cocoapods
-
生成 release 包
Qt Creator 左下角切换为 Release 模式,然后点击左下角 Build 锤子🔨图标。
定位到构建文件夹 Build directory
可在 Projects -> Build Settings 中找到:Build directory。
使用 macdeployqt 工具打包 .app 文件
工具所在目录:~/Qt/6.2.3/macos/bin
./macdeployqt $Build directory$/***.app