瀏覽代碼

新增文档

xiannian.mu 1 年之前
父節點
當前提交
a606d66722

二進制
.DS_Store


+ 0 - 0
README.md


+ 0 - 0
关于标准桌面中酒店菜单开关解耦,终端的适配方案/image-20230828171015608.png


+ 0 - 0
关于标准桌面中酒店菜单开关解耦,终端的适配方案/image-20230828171158073.png


+ 11 - 1
关于标准桌面中酒店菜单开关解耦,终端的适配方案/关于标准桌面中酒店菜单开关解耦,终端的适配方案.md

@@ -2,10 +2,16 @@
 
 ### 1、应用禁用
 
+#### 1.1、顶级白名单
+
 提供应用禁用顶级白名单 TOP_APP_DISABLE_IGNORE_LIST。
 
 白名单包含标准桌面的包名[com.tcl.btv.mode],管控在实际禁用APP之前移除顶级白名单中的包名。
 
+#### 1.2 launcher禁用逻辑
+
+通用模式下依据launcher进行应用禁用(之前是直接设置cyberUI),关注launcher为空的情况(获取默认launcher)。
+
 ### 2、管控注册和上报
 
 管控注册和上报取消对当前酒店模式的判断。
@@ -34,4 +40,8 @@
 
 ![image-20230828171015608](./image-20230828171015608.png)
 
-点我直接访问:https://boardmix.cn/app/share/CAE.CIvHpQwgASoQPQD0ufnMS4Y0WnriwOVg7zAFQAE/AhkfFx
+点我直接访问:https://boardmix.cn/app/share/CAE.CIvHpQwgASoQPQD0ufnMS4Y0WnriwOVg7zAFQAE/AhkfFx
+
+#### **4.3 待确认**
+
+之前的授权方案是酒店模式下,现在开放成通用模式和酒店模式之后,授权流程是否需要有调整。

+ 0 - 0
关于标准桌面中酒店菜单开关解耦,终端的适配方案/离线授权流程图-导出.png


+ 94 - 0
泰康视频通话/泰康视频通话代码结构.md

@@ -0,0 +1,94 @@
+# 1、代码下载
+
+https://git.tclyun.cn/AwesomeHotel/TaikangVideoCall.git
+
+# 2、编译环境
+
+Android Studio版本: 2022.2.1 Patch 2
+
+jdk版本:Java 11
+
+Gradle Plugin Version:7.0.4
+
+Gradle Version:7.5
+
+Kotlin版本:1.8.0
+
+# 3、代码结构
+
+## 3.1 app
+
+### 1、监听开机广播进行视频通话SDK初始化
+
+```kotlin
+com.tcl.ah.tkvideocall.receiver.TclBroadcastReceiver
+```
+
+### 2、添加前台服务,提高应用存活率
+
+```kotlin
+com.tcl.ah.tkvideocall.service.TKForegroundService
+```
+
+### 3、新增自定义广播被比利APP拉起
+
+```kotlin
+com.tcl.ah.tkvideocall.receiver.NotifyBroadcastReceiver
+```
+
+### 4、处理APP自升级
+
+```kotlin
+com.tcl.ah.tkvideocall.utils.UpdateHelper
+```
+
+### 5、处理泰康的数据收集
+
+```kotlin
+com.tcl.ah.tkvideocall.http.NetHelper
+```
+
+## 3.2 tuicallkit-kt
+
+### 1、tuicallkit
+
+这个是腾讯通话SDK提供的UI源码,主要负责视频通话底层的实现
+
+### 2、vodeo_call
+
+基于视频通话SDK底层的实现,开发出的适合业务的UI层面。
+
+#### 2.1 config
+
+主要配置定制参数属性,包括APPSDKID,SECRETKEY,泰康的后台接口HOST,通过超时时间等等。
+
+#### 2.2 hepler
+
+针对通话,对话框,im,按键监听,日志,登录和录制功能提供了对应的帮助类
+
+#### 2.3 listener
+
+对外暴露的时间监听总入口,给到app或者其他模块使用
+
+#### 2.4 model
+
+通用数据模型
+
+#### 2.5 utils
+
+通用工具类
+
+#### 2.6 view
+
+通用View的自定义模块,包含提示View,对话框View,视频录制View和功能切换View,方便在不同场景下的复用和解耦
+
+####  [TaikangVideoCallHelper.kt](../../../tcl/TaikangVideoCall/tuicallkit-kt/src/main/java/com/tencent/qcloud/tuikit/video_call/TaikangVideoCallHelper.kt) 
+
+module对外开放的统一入口,所有对外的交互都在这个统一入口体现。
+
+
+
+
+
+
+

File diff suppressed because it is too large
+ 234 - 0
泰康视频通话/泰康视频通话技术文档.md


+ 513 - 0
管控963和920差异/管控963和920差异.md

@@ -0,0 +1,513 @@
+## 一、管控APP功能分析
+
+### 1、包含的服务
+
+#### 1.1、BackService
+
+系统启动成功之后,如果打开酒店模式或者网络变化,就会打开TclIntentService,之后每半小时启动一次service。
+
+#### 1.2、TclIntentService
+
+-  接受action为connect_server
+
+- - 接受index_order
+
+  - - REQUEST_CHECK_APK
+
+​    自升级和更新
+
+- - - SYSTEM_MODE_CHANGED
+
+  禁用APP,启用默认APP
+
+- - - REQUEST_CHECK_OTA
+
+​       检测OTA升级
+
+- 接受action为com.android.systemservice.MANAGEMENT_APP
+
+​     禁用APP,启用默认APP
+
+#### 1.3、TvOnlineService
+
+- /api/tvlogs/tv_turn_on  上报数据
+
+#### 1.4、AppOnlineService
+
+- /api/tvlogs/tv_app_turn_on 上报数据
+
+#### 1.5、GrantService
+
+- action 为 com.tcl.grant.AUTH 或者 action 为com.android.systemservice.auth.CHANGED
+
+​      延迟20s之后,如果酒店模式打开了,调用 /api/terminal2 接口 进行注册。
+
+注册成之后调用 /api/heartbeat2 获取在线授权信息。然后按照接口返回的心跳时间进行下一次操作。
+
+- 应用自升级(应用平台)
+
+### 2、包含的广播
+
+#### 2.1、ManagementReceiver
+
+-  启动成功或者收到TCL 的P0广播
+
+- - 启动 TclIntentService ,action 为 ACTION_MANAGEMENT_APP, 禁用APP,启用默认APP
+  - 如果开启酒店模式,发送com.tcl.grant.AUTH,启动GrantService
+  - 检查授权信息
+
+-  启动成功
+
+- - 启动 TvOnlineService ,调用 /api/tvlogs/tv_turn_on 
+  - 启动 AppOnlineService,调用 /api/tvlogs/tv_app_turn_on
+  - 如果开启酒店模式,发送com.tcl.grant.AUTH,启动GrantService
+  - 检查APP更新,检查OTA更新
+
+-  收到TCL P0广播
+
+- - 注册网络变化广播
+  - 启动TclIntentService,action为 connect_server,index_order 为 SYSTEM_MODE_CHANGED,禁用APP,启用默认APP
+
+-  网络变化或者酒店模式改变
+
+- - 启动TclIntentService,action为 connect_server,index_order 为 SYSTEM_MODE_CHANGED,禁用APP,启用默认APP
+  - 如果开启酒店模式,发送com.tcl.grant.AUTH,启动GrantService
+
+- 检测USB挂载
+
+检查U盘更目录下的 /installation/installation文件的installation字段,如果是true就打开GrantActivity
+
+#### 2.2、TclBroadcastReceiver
+
+- 启动成功
+
+- - 启动 BackService -> 启动TclIntentService 
+
+​    action 为 connect_server,index_order 为 REQUEST_CHECK_ALIVE 空实现
+
+- 网络变化或者action为ACTION_OTA_TEST(com.android.systemservice.OTA_TEST)
+
+- - 启动 BackService -> 启动TclIntentService 
+
+​    action 为 connect_server,index_order 为 REQUEST_CHECK_ALIVE 空实现
+
+- - 启动TclIntentService,action为 connect_server ,附带参数 index_order 分别为 REQUEST_CHECK_APK,REQUEST_REGISTER,REQUEST_CHECK_OTA
+
+  - - REQUEST_CHECK_APK
+
+  调用 api/upgrade 接口下载和更新apk
+
+- - - REQUEST_REGISTER
+
+​        空实现
+
+- - - REQUEST_CHECK_OTA
+
+​        ota升级逻辑
+
+- 检测USB端口挂载
+
+本地离线授权
+
+- 检测外设摄像头插拔
+
+​      插:展示摄像头信息,拔:关闭摄像头
+
+### 3、主要功能汇总
+
+#### 3.1、自更新和升级,包括应用平台
+
+#### 3.2、APK管理,包括禁用和启用
+
+#### 3.3、检测OTA升级(管控后台)
+
+#### 3.4、向/api/tvlogs/tv_turn_on  上报数据(可以考虑去掉)
+
+#### 3.5、向/api/tvlogs/tv_app_turn_on 上报数据(可以考虑去掉)
+
+#### 3.6、酒店注册  /api/terminal2
+
+#### 3.7、获取在线授权信息 /api/heartbeat2
+
+#### 3.8、本地离线授权和在线授权结合
+
+#### 3.9、检测外设摄像头挂载(暂时没有用到,)
+
+## 二、963和920差异对比
+
+### 1、TclIntentService
+
+com.android.systemservice.server.TclIntentService
+
+```
+//920上的实现
+private List<String> getDisableList(AppInfo info, String softVersion) {
+        //这里不一致
+        if (info == null || softVersion == null || softVersion.trim().length() == 0) {
+            return null;
+        }
+        String ver = softVersion.substring(0, 7);
+        Log.i(TAG, "ver:" + ver);
+        switch (ver) {
+            case Constants.SOFT_VERSION_A260:
+                return info.getDisableA26X();
+            case Constants.SOFT_VERSION_A360:
+                return info.getDisableA36X();
+            case Constants.SOFT_VERSION_G5X://这里不一致
+                return info.getDisableG5X();//这里不一致
+            default:
+                return info.getDisable();
+        }
+    }
+//963上的实现
+private List<String> getDisableList(AppInfo info, String softVersion) {
+              //这里不一致
+        if (info == null || softVersion == null || softVersion.trim().length() < 7) {
+            return null;
+        }
+        String ver = softVersion.substring(0, 7);
+        Log.i(TAG, "ver:" + ver);
+        switch (ver) {
+            case Constants.SOFT_VERSION_A260:
+                return info.getDisableA26X();
+            case Constants.SOFT_VERSION_A360:
+                return info.getDisableA36X();
+            case Constants.SOFT_VERSION_T972://这里不一致
+                return info.getDisableA26X(); //这里不一致
+            default:
+                return info.getDisable();
+        }
+    }
+```
+
+### 2、Constants
+
+com.android.systemservice.utils.Constants
+
+```
+  //920
+  public static final String SOFT_VERSION_A260 = "V8-S38P";
+  public static final String SOFT_VERSION_A360 = "V8-A962";
+  public static final String SOFT_VERSION_G5X = "V8-A920";
+
+
+  //963
+  public static final String SOFT_VERSION_A260 = "V8-S38P";
+  public static final String SOFT_VERSION_A360 = "V8-A962";
+  public static final String SOFT_VERSION_T972 = "V8-A972";
+    public static final String ANDROID = "android";
+```
+
+### 3、AppInfo
+
+com.tcl.app.AppInfo
+
+```
+//920
+public List<String> getDisableG5X(){
+    return DisableAppG5X.list;
+}
+
+
+AwesomeHotelDisable@add
+public void add() {
+  awsomeHotelDisable.add(AWSOME_HOTEL2);
+  awsomeHotelDisable.add(APP_MANAGER);
+  awsomeHotelDisable.add(UPDATE);
+}
+
+
+DisableAppA26X#list
+public List<String> list = Arrays.asList("com.android.tcl.messagebox", "com.tcl.c2dm.client",
+                "com.tcl.appmarket2", "tv.huan.tvhelper", "com.tcl.MultiScreenInteraction_TV", "com.droidlogic.miracast",
+                "com.hpplay.allcast", "com.huan.edu.lexue.frontend", "com.tcl.browser", "com.audiocn.kalaok.tv",
+                "com.android.keychain", "com.tcl.SmartTVHelp", "com.tcl.bootadservice", "com.tcl.tv.jtq",
+                "com.tcl.esticker", "com.tcl.appmarket2", "cn.wps.moffice_i18n_TV", "com.tcl.tshop",
+                "com.tcl.weixin", "com.tcl.screensaver", "com.tcl.common.weather", "com.tcl.usagestats",
+                "com.tcl.usercenter", "com.tcl.vod", "com.tcl.wholenetsearch", "com.tcl.gamecenter",
+                "com.golive.cinema", "com.tcl.tvweishi");
+
+
+DisableAppA36X#list
+public final List<String> list = Arrays.asList("com.android.tcl.messagebox", "com.tcl.c2dm.client",
+                "com.tcl.appmarket2", "tv.huan.tvhelper", "com.tcl.MultiScreenInteraction_TV", "com.droidlogic.miracast",
+                "com.hpplay.allcast", "com.tcl.tshop", "com.golive.cinema", "com.audiocn.kalaok.tv",
+                "com.tcl.weixin", "com.tcl.vod", "com.tcl.tvhealthcheck", "cn.wps.moffice_i18n_TV",
+                "com.tcl.browser", "com.tcl.bootadservice", "com.tcl.screensaver", "com.tcl.usagestats",
+                "com.tcl.tv.jtq", "com.tcl.gamecenter", "com.tcl.triava", "com.tcl.common.weather",
+                "com.tcl.wholenetsearch", "com.tcl.SmartTVHelp", "com.huan.edu.lexue.frontend", "com.tcl.voicemanager",
+                "com.tcl.usercenter", "com.tcl.tvweishi");
+
+
+DisableAppG5X#list
+public static final List<String> list = Arrays.asList("com.pptv.tvsports.preinstall","com.tcl.wholenetsearch",
+                "com.tcl.initsetup","com.tcl.common.weather","com.golive.cinema","com.tcl.browser",
+                "com.tcl.appmarket2","com.tcl.tshop","com.android.tcl.messagebox",
+                "com.tcl.vod","com.tcl.weixin","com.tcl.SmartTVHelp","com.tcl.gamecenter",
+                "com.tcl.usercenter","com.tcl.tvweishi","com.tcl.ffeducation","com.tcl.c2dm.client",
+                "com.tcl.usagestats");
+
+
+//963
+AwesomeHotelDisable@add
+public void add() {
+  awsomeHotelDisable.add(AWSOME_HOTEL);
+  awsomeHotelDisable.add(AWSOME_HOTEL2);
+  awsomeHotelDisable.add(APP_MANAGER);
+}
+
+
+DisableAppA26X#list
+public List<String> list = Arrays.asList("com.android.tcl.messagebox", "com.tcl.c2dm.client",
+                "com.tcl.appmarket2", "tv.huan.tvhelper", "com.tcl.MultiScreenInteraction_TV", "com.droidlogic.miracast",
+                "com.hpplay.allcast", "com.tcl.tvweishi", "com.huan.edu.lexue.frontend", "com.tcl.browser",
+                "com.audiocn.kalaok.tv", "com.android.keychain", "com.tcl.SmartTVHelp", "com.tcl.bootadservice",
+                "com.tcl.tv.jtq", "com.tcl.esticker", "com.tcl.appmarket2", "cn.wps.moffice_i18n_TV", "com.tcl.tshop",
+                "com.tcl.weixin", "com.tcl.screensaver", "com.tcl.common.weather", "com.tcl.usagestats", "com.tcl.usercenter",
+                "com.tcl.vod", "com.tcl.wholenetsearch", "com.tcl.gamecenter", "com.golive.cinema");
+
+
+DisableAppA36X#list
+public final List<String> list = Arrays.asList("com.android.tcl.messagebox", "com.tcl.c2dm.client",
+                "com.tcl.appmarket2", "tv.huan.tvhelper", "com.tcl.MultiScreenInteraction_TV", "com.droidlogic.miracast",
+                "com.hpplay.allcast", "com.tcl.tvweishi", "com.tcl.tshop", "com.golive.cinema",
+                "com.audiocn.kalaok.tv", "com.tcl.weixin", "com.tcl.vod", "com.tcl.tvhealthcheck", "cn.wps.moffice_i18n_TV",
+                "com.tcl.browser", "com.tcl.bootadservice", "com.tcl.screensaver", "com.tcl.usagestats",
+                "com.tcl.tv.jtq", "com.tcl.gamecenter", "com.tcl.triava", "com.tcl.common.weather", "com.tcl.wholenetsearch",
+                "com.tcl.SmartTVHelp", "com.huan.edu.lexue.frontend", "com.tcl.voicemanager", "com.tcl.usercenter");
+```
+
+### 4、ManagementReceiver
+
+com.tcl.broadcast.ManagementReceiver
+
+```
+//963比920多了
+//在ACTION_BOOT_COMPLETED之后
+应用自升级检测
+ota升级检测
+```
+
+### 5、GrantActivity
+
+com.tcl.grant.GrantActivity  以963方式为主
+
+```
+//920
+private void initGrantInfo(){
+        mMac = TVUtils.getEthMacAddress();
+        mGrantInfo = new DeviceInfo();
+        mGrantInfo.setMac(mMac==null?mMac:mMac.replace(":",""))
+                .setMachineType(TVUtils.getModelName(getApplicationContext()))
+                .setVersion(HotelUtils.getAgencyVersion(getApplicationContext()))
+                .setVer(TVUtils.getSoftwareVersion()) //这里
+                .setLauncher(mLauncher);
+    }
+//963
+private String getSoftwareVersion() {
+        if (mCustomerApiHandler.getCustomerApi() != null) {
+            try {
+                return mCustomerApiHandler.getCustomerApi().getSoftwareVersion();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return TVUtils.getSoftwareVersion();
+    }
+```
+
+### 6、HotelUtils
+
+com.tcl.hoteltv.factory.HotelUtils  (此方法使用920的方式,但是要改动)
+
+```
+//920
+public static String getDefaultAgencyVersion(Context context){
+        StringBuilder builder = new StringBuilder();
+        builder.append("TCL-")
+                .append(TVUtils.getModelName(context))
+//                .append("G60")
+                .append("-20200325-V000");
+        return builder.toString();
+    }
+//963
+public static String getDefaultAgencyVersion(Context context) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("TCL-")
+                //.append(TVUtils.getModelName(context))
+                .append("G60")
+                .append("-20200325-V000");
+        return builder.toString();
+    }
+```
+
+### 7、TVUtils
+
+com.tcl.hoteltv.factory.TVUtils  (用920的方式,需要验证)
+
+```
+//920
+ public static String getModelName(Context context) {
+        String versionName = getSoftwareVersion();
+        if (versionName.contains(Constants.SOFT_VERSION_G5X)) {
+            return FactoryManager.getInstance(context).doGetProjectName();
+        } else {
+            return TDeviceInfo.getInstance().getModelName(getProjectIDValue(context));
+        }
+    }
+
+
+//963
+public static String getModelName(Context context) {
+        return TDeviceInfo.getInstance().getModelName(getProjectIDValue(context));
+    }
+```
+
+### 8、Files
+
+com.tcl.utils.Files
+
+```
+//920
+public static void changePermission(String path){
+        FileUtils.setPermissions(path, FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IRWXO, -1, -1) ;
+    }
+//963
+public static void changePermission(String path){
+        MyFileUtils.setPermissions(path);
+        //FileUtils.setPermissions(path, FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IRWXO, -1, -1) ;
+    }
+```
+
+### 9、jar包整理
+
+#### 两个机型都有的jar包:
+
+ah-extension-1.0.1.aar
+
+ 
+
+920文件md5:0794a887e3b80205854a3e3a4edc346d
+
+-  963文件md5:0794a887e3b80205854a3e3a4edc346d
+
+appassistsdk-2.0.11.aar
+
+ 
+
+920文件md5:a53bb0b822fb8245855bdcdf3add9783
+
+-  963文件md5:a53bb0b822fb8245855bdcdf3add9783
+
+com.tcl.customerapi.jar
+
+ 
+
+920文件md5:75802fa86e077513cf058db99cf4359f
+
+-  963文件md5:469bca8de85ca2c19c6ba9557e850425
+
+com.tcl.tvos.addon.jar
+
+ 
+
+920文件md5:2621d0f692fc8c4c83e8750efe5b5bfc
+
+-  963文件md5:2621d0f692fc8c4c83e8750efe5b5bfc
+
+factory.jar
+
+ 
+
+920文件md5:3a3895919fb0a80e93eae9ea8402536f
+
+-  963文件md5:3a3895919fb0a80e93eae9ea8402536f
+
+fastjson-1.1.51.android.jar
+
+ 
+
+920文件md5:24295b91c61c7a64dcba6b5518915867
+
+-  963文件md5:24295b91c61c7a64dcba6b5518915867
+
+framework.jar
+
+ 
+
+920文件md5:4146ff34d7040bc93470e6adddf9439a
+
+-  963文件md5:4146ff34d7040bc93470e6adddf9439a
+
+services.jar
+
+ 
+
+920文件md5:327debb1084d31350e4b721adea601b8
+
+-  963文件md5:327debb1084d31350e4b721adea601b8
+
+snack-1.0.2.aar
+
+ 
+
+920文件md5:cc2f1a12750505b0777e0e93d6be8a07
+
+-  963文件md5:cc2f1a12750505b0777e0e93d6be8a07
+
+tornado-0.1.4.jar
+
+ 
+
+920文件md5:01817d2b50ad9f5bfd1871095c208ee5
+
+-  963文件md5:01817d2b50ad9f5bfd1871095c208ee5
+
+tvapi.jar
+
+ 
+
+920文件md5:45949462ec4ec42ac6eb5d84ffe7da72
+
+-  963文件md5:45949462ec4ec42ac6eb5d84ffe7da72
+
+zxing-core-3.3.3.jar
+
+ 
+
+920文件md5:3ee2c714be5d25ac6c9b941f666bfea6
+
+-  963文件md5:3ee2c714be5d25ac6c9b941f666bfea6
+
+#### 仅963有的jar包
+
+- rainbow-0.1.jar
+- virtualApi-0.1.jar
+
+## 三、合并方案
+
+### 1、合并方式
+
+有三种合并方式。
+
+一种是不动代码结构,仅根据两者差异在差异点进行不同机型的适配,根据两个项目中源码对比的结果来看,此方法是可行的。此方法优点在于改动量小,而且基本能保证之前的功能。
+
+第二种是大改代码结构,将整个项目进行重构,根据功能进行模块划分和重组。此方法的优点是可以趁机统一下代码风格,缺点是周期长,改动大,而且可能会丢失之前已经存在的功能。
+
+第三种是前两者的结合,首先使用第一种方式完成不同机型的兼容。对项目内的部分功能点进行抽离和整理。
+
+我个人建议采用第三种方式。
+
+### 2、建议抽离的功能点
+
+#### 2.1、更新功能
+
+包括应用自升级和ota升级的逻辑可以抽离到一起,提供统一入口
+
+#### 2.2、数据上报相关
+
+提供统一的入口,定时进行数据上报。包括注册和心跳
+
+#### 2.3、授权相关
+
+## 离线授权和在线授权的整合 

二進制
翻译系统/images/image-20231219093938488.png


二進制
翻译系统/images/image-20231219094255713.png


二進制
翻译系统/images/image-20231219094415225.png


二進制
翻译系统/images/image-20231219094623041.png


二進制
翻译系统/images/image-20231219095207071.png


二進制
翻译系统/images/image-20231219095225303.png


二進制
翻译系统/images/image-20231219095415889.png


+ 206 - 0
翻译系统/翻译系统实现方案.md

@@ -0,0 +1,206 @@
+## 1、项目意义
+
+项目逐渐走向海外版本,翻译就变成一个很重要切必须做的事情。
+
+### 1.1 传统方式
+
+现阶段,项目中字段的翻译步骤如下:
+
+1、分别收集项目中不同模块的翻译key和翻译value
+
+Android 国际化配置文件
+
+```xml
+<resources>
+    <string name="app_name">翻译助手</string>
+    <string name="str_from_app">你好</string>
+    <string name="str_from_app1">生活是美好的</string>
+    <string name="str_from_app2">人性是复杂的</string>
+    <string name="str_from_app3">点击按钮退出页面</string>
+    <string name="str_from_app4">你叫什么名字</string>
+</resources>
+```
+
+PHP中 laravel 框架使用的配置文件
+
+```php
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Password Reminder Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are the default lines which match reasons
+    | that are given by the password broker for a password update attempt
+    | has failed, such as for an invalid token or invalid new password.
+    |
+    */
+
+    'password' => '密码至少是六位字符并且匹配。',
+    'reset'    => '密码重置成功!',
+    'sent'     => '密码重置邮件已发送!',
+    'token'    => '密码重置令牌无效。',
+    'user'     => '找不到该邮箱对应的用户。',
+
+];
+
+```
+
+2、将收集到的key-value按模块复制粘贴到excel文档中
+
+3、将文档交付给第三方去进行翻译,将翻译好的文档交付给我们开发
+
+4、将翻译好的内容依次回填到项目中其他语言的配置文件中
+
+### 1.2 弊端
+
+1、操作耗时
+
+对于开发人员来讲,这件事是没有技术含量却很复杂的,项目中需要翻译的字段可能上千个甚至几千个,光收集内容和最后将翻译内容填充到项目可能需要花上几天的时间
+
+2、容易出错
+
+操作的过程中需要保持高度集中,如果一旦出现复制出错,会导致翻译内容对不上
+
+3、翻译人员操作也很痛苦
+
+翻译人员将翻译好的内容一个个复制到excel也很痛苦。
+
+### 3.1 系统带来的好处
+
+1、国际化配置文件中的key和value可以通过程序自动收集
+
+2、翻译好的内容也可以通过程序一键在本地生成好其他国家语言的配置文件
+
+3、翻译人员可以在网站上进行翻译,友好的交互,同时提供了自动翻译的功能
+
+4、适配Android,PHP以及后续可能会适配的前端Vue,小程序框架等等项目,让翻译这件事情能够统一
+
+## 2、项目架构
+
+### 2.1 项目实现
+
+项目分为三个板块,分为开发使用的:翻译桌面端  翻译人员使用的:翻译管理后台 和 为他们提供数据服务支持的翻译API后台。目前PC端的软件已经全部生成,后台管理系统和服务端已经分别部署到腾讯云服务器,可直接访问。
+
+#### 2.1.1 翻译桌面端
+
+技术栈:使用 Electron + Vue3,分别打包 Mac(intel芯片),Mac(Apple芯片)和Windows软件
+
+功能:开发人员用于上传本地翻译内容到服务端和拉去服务端的翻译在本地合成国际化翻译文件
+
+#### 2.1.2 翻译管理后台
+
+技术栈:Vue2
+
+功能:
+
+1、创建项目
+
+2、在线对内容进行翻译
+
+#### 2.1.3 API后台
+
+技术栈:Springboot + MySql
+
+功能:为桌面端和管理后台提供API支持
+
+### 2.2 系统使用
+
+#### 2.2.1 访问管理后台
+
+http://tcl.mxnzp.com/admin-translate/#/home
+
+#### 2.2.2 点击控制台管理进入登录页面
+
+```
+账号:13227293721
+密码:cretin**29**
+```
+
+#### 2.2.3 下载桌面工具
+
+登录成功之后点击控制台管理进入后台管理页面,点击左侧桌面工具下载对应你当前系统的桌面工具并安装
+
+#### 2.2.4 登录桌面工具
+
+点击右上角用户信息,点击获取token,等到登录用的token
+
+![image-20231219093938488](./images/image-20231219093938488.png)
+
+#### 2.2.5 在管理后台创建项目
+
+点击项目列表,点击新建项目,输入项目名称,项目描述和项目平台,平台目前仅支持Android和PHP。
+
+#### 2.2.6 选择项目和完善地址
+
+打开翻译桌面端,用在2.2.4中获取的token进行登录,登录成功会弹出选择项目弹窗,选择你刚刚创建的项目。然后点击选择文件夹按钮选择项目根目录即可。
+
+![image-20231219094255713](./images/image-20231219094255713.png)![image-20231219094415225](./images/image-20231219094415225.png)
+
+#### 2.2.7 上传翻译
+
+点击桌面端左侧上传翻译,点击顶部拉去本地资源,拉取成功之后会展示当前项目中所有的翻译Key和Value,检查无误之后点击顶部的上传数据到云端即可。
+
+![image-20231219094623041](./images/image-20231219094623041.png)
+
+#### 2.2.8 进行翻译
+
+打开管理后台,点击左侧的项目列表,选择你刚刚创建的项目,点击进入翻译系统。未翻译的地方都会显示点击翻译,点击“点击翻译”会弹出翻译窗口,在这里提供了在线翻译的功能,将翻译后的内容填入输入框,按SHIFT+回车或者点击确定按钮完成翻译。
+
+![image-20231219095207071](./images/image-20231219095207071.png)
+
+![image-20231219095225303](./images/image-20231219095225303.png)
+
+#### 2.2.9 拉取翻译
+
+打开翻译桌面端,点击左边的同步翻译,点击顶部拉取云端翻译,会展示云端已经翻译好的内容,点击生成本地数据即可在本地生成其他国家的语言翻译配置。
+
+![image-20231219095415889](./images/image-20231219095415889.png)
+
+#### 2.2.10 查看翻译文件
+
+**以PHP为例**
+
+此处是未翻译之前的内容
+
+```php
+<?php
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Password Reminder Language Lines
+    |--------------------------------------------------------------------------
+    |
+    | The following language lines are the default lines which match reasons
+    | that are given by the password broker for a password update attempt
+    | has failed, such as for an invalid token or invalid new password.
+    |
+    */
+
+    'password' => '密码至少是六位字符并且匹配。',
+    'reset'    => '密码重置成功!',
+    'sent'     => '密码重置邮件已发送!',
+    'token'    => '密码重置令牌无效。',
+    'user'     => '找不到该邮箱对应的用户。',
+
+];
+
+```
+
+此处是翻译之后的内容
+
+```php
+<?php
+
+return [
+    'password' => 'The password must be at least six characters and match.',
+    'reset' => 'Password reset successful!',
+    'sent' => 'Password reset email has been sent!',
+];
+```
+