From 35bc880637ba766a4a520fa2027a5680d67b24f1 Mon Sep 17 00:00:00 2001 From: "BenderBlog \"SuperBart\" Rodriguez" Date: Fri, 4 Oct 2024 20:27:34 +0800 Subject: [PATCH 1/4] feat: i18n 30% with all string in program --- assets/flutter_i18n/zh_CN.yaml | 565 ++++++++++++++++++ lib/main.dart | 15 +- lib/page/homepage/home.dart | 155 +++-- .../xidian_ids/library_session.dart | 5 +- pubspec.lock | 24 + pubspec.yaml | 12 +- 6 files changed, 691 insertions(+), 85 deletions(-) create mode 100644 assets/flutter_i18n/zh_CN.yaml diff --git a/assets/flutter_i18n/zh_CN.yaml b/assets/flutter_i18n/zh_CN.yaml new file mode 100644 index 00000000..24f6920d --- /dev/null +++ b/assets/flutter_i18n/zh_CN.yaml @@ -0,0 +1,565 @@ +# EasyRefresh 下拉插件的玩意 +drag_text: "上拉请求更多" +ready_text: "正在加载......" +processing_text: "正在加载......" +processed_text: "请求成功" +noMore_text: "数据没有更多" +failed_text: "数据获取失败更多" + +# 公共组件 +choose_semester: "选择学期" +error_detected: "Ouch! 发生错误啦" +click_to_refresh: "点我刷新" + +# 取消和确定 +cancel: "取消" +confirm: "确定" + +# controller/model 里面可能需要给用户展示的 +network_error: "网络错误,可能是没联网,可能是学校服务器出现了故障:-P" +error_detect: "遇到错误: {e}" +query_failed: "查询失败" +not_school_network: "没有在校园网环境" +experiment_controller: + no_password: "没有物理实验密码" + login_failed: "登录失败" +cancel_exam: "取消考试资格:P" +electricity_session: + fetching: "正在获取" + not_school_network: "非校园网" + network_problem: "网络故障" + query_failed: "查询失败" + program_crash: "程序故障" +login_process: + ready_page: "准备获取登录网页" + get_encrypt: "获取密码加密密钥" + ready_login: "准备登录" + slider: "滑块验证" + after_process: "登录后处理" + failed: "登录失败,响应状态码:{statusCode}" +# TODO: ehall_exam_session data + +# main.dart 里面 Catcher 插件字符串 +catcher: + error_detected: "发生错误" + error_description: "详情如下" + +# 登录界面 +login: + identity_number: "学号" + password: "一站式登录密码" + login: "登录" + incorrect_password_pattern: "用户名或密码不符合要求,学号必须 11 位且密码非空" + on_login_progress: "正在登录学校一站式" + complete_login: "登录成功" + failed_login_cannot_connect_to_server: "无法连接到服务器" + failed_login_with_code: "请求失败,响应状态码:{code}" + failed_login_with_message: "请求失败,报错信息:{message}" + failed_login_other: "未知错误,请联系开发者" + bottom_buttons: + clear_cache: "清除登录缓存" + complete_clear_cache: "清理缓存成功" + see_inspector: "查看网络交互" + captcha_window: + title: "请输入验证码" + hint: "输入验证码" + message_on_empty: "请输入验证码" + slider: + title: "服务器认证服务" + +# 日程表/课程表 +classtable: + weekday: + monday: "周一" + tuesday: "周二" + wednesday: "周三" + thursday: "周四" + friday: "周五" + saturday: "周六" + sunday: "周日" + partner_classtable: + override_dialog: + title: "确认对话框" + message: "目前有搭子课表数据,是否要覆盖?" + message: + no_file: "未发现导入文件" + no_permission: "未获取存储权限,无法读取文件" + problem: "好像导入文件有点问题:P" + success: "导入成功" + share_dialog: + title: "请不要随意分享" + hint: "导出文件包括你的个人信息,请不要随意跟别人分享,或者发在大群里。" + save_dialog: + title: "保存日历文件到..." + success_message: "应该保存成功" + failure_message: "文件创建失败,保存取消" + delete_dialog: + title: "确认对话框" + message: "确定要清除共享课表吗?" + success_message: "删除共享课表成功" + page_title: "我的日程表" + partner_page_title: "搭子的日程表" + popup_menu: + not_arranged: "查看未安排课程信息" + class_changed: "查看课程安排调整信息" + add_class: "添加课程信息" + generate_ical: "生成日历文件" + generate_partner_file: "生成共享课表文件" + import_partner_file: "导入共享课表文件" + delete_partner_file: "删除共享课表文件" + class_change_page: + title: "课程调整" + empty_message: "目前没有调课信息" + teacher_change: "从{previous_teacher}变为{new_teacher}" + no_teacher_change: "教师信息没有改变" + change_class_message: 调课信息,从第{originalAffectedWeeks}周 + 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}节 + 调整为第{newAffectedWeeksListStr}周星期{weekChar_newWeek}的 + {newClassRangeStart}-{newClassRangeStop}节,{newClassroom}教室上课 + patch_class_message: 补课信息,从第{newAffectedWeeksListStr}周 + 星期{weekChar_newWeek}的{newClassRangeStart}-{newClassRangeStop}节, + {newClassroom}补课 + stop_class_message: 停课信息,第{originalAffectedWeeks}周 + 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}节 + {originalClassroom}停课 + class_info: "编号: {classCode} | {classNumber} 班\n安排变更:{classChange}" + not_arranged_page: + title: "没有时间安排的科目" + empty_message: "目前全部课程均有时间安排" + content: "编号: {classCode} | {classNumber} 班\n老师: {teacher}" + empty_class_message: "{semester_code} 学期没有课程" + week_title: "第{week}周" + noon_break: "午休" + supper_break: "晚休" + class_card: + title: "日程信息" + unknown_classroom: "未知教室" + remains_hint: "还有{remain_count}个日程" + class_add: + add_class_title: "添加课程" + change_class_title: "修改课程" + class_name_empty_message: "必须输入课程名" + wrong_time_message: "输入的时间不对" + save_button: "保存" + input_classname_hint: "课程名字(必填)" + input_teacher_hint: "老师姓名(选填)" + input_classroom_hint: "教室位置(选填)" + input_week_hint: "选择上课周次" + input_time_hint: "选择上课时间" + input_time_weekday_hint: "上课周次" + input_start_time_hint: "上课时间段" + input_end_time_hint: "下课时间段" + wheel_choose_hint: "第 {index} 节" + course_detail_card: + class_number_string: "{number} 班" + unknown_teacher: "老师未定" + unknown_place: "地点未定" + class_period: "{start}-${stop}节" + edit: "编辑" + delete: "删除" + delete_confirm_dialog: + title: "是否删除课程信息?" + content: "所有关于这个课的信息都会被删除,课表上关于这门课的信息将不复存在!" + +# 双创信息 +creative_job: + search_hint: "搜索需求" + choice_type: "选择种类" + position_type: "职位类型" + no_result: "没有搜索到结果" + please_search: "请在上面搜索框搜索" + query_for_person: "招募 {exceptNumber} 人 · " + end_time: "截止日期 {end_time}" + complete_choosing: "选择完毕" + creative_job_description: + title: "工作详情" + browser_hint: "*如果用户感兴趣,请按右上角的按钮在浏览器中打开*" + job_description_title: 岗位描述 + reward_title: 工作回报 + progress_title: 项目进度 + no_description: 没有描述 + +# 空闲教室 +empty_classroom: + title: "空闲教室" + date: "日期 {date}" + building: "教学楼 {building}" + search_hint: "教室名称或者教室代码" + classroom: "教室" + +# 考试信息 +exam: + title: "考试安排" + cache_hint: "已显示缓存考试安排信息" + not_finished: "未完成考试" + all_finished: "所有考试全部完成" + unable_to_exam: "无法完成考试" + finished: "已完成考试" + none_finished: "一门还没考呢" + no_exam_arrangement: "目前没有考试安排" + no_arrangement: + title: "目前无安排考试的科目" + all_arranged: "目前所有科目均已安排考试" + subtitle: "编号: {id}" + +# 物理实验 +experiment: + title: "物理实验" + ongoing: "正在进行实验" + not_finished: "未完成实验" + all_finished: "所有实验全部完成" + finished: "已完成实验" + score_sum: "目前分数总和:{sum}" + none_finished: "目前没有已经完成的实验" + not_provided: "未提供" + +# 主页 +homepage: + time_string: + morning: "早上好 准备出发" + before_noon: "上午好 祝万事如意" + at_noon: "中午好 一切还好吧" + afternoon: "下午好 今天如何" + night: "晚上好 祝你好梦" + midnight: "深宵了 我在陪你" + loading: "正在加载" + load_error: "加载错误" + on_holiday: "假期中" + on_weekday: "第 ${c.getCurrentWeek(updateTime) + 1} 周" + loading_message: "请稍候,正在刷新信息" + homepage: "主页" + xdu_planet: "博客星球" + setting: "设置" + input_partner_data: + route_not_exist: "导入路径不存在:P" + failed_get_file: "导入文件失败" + failed_import: 好像导入文件有点问题:P + success_message: "导入成功,如果打开了课表页面请重新打开" + not_loaded: "还没加载课程表,等会再来吧……" + confirm_dialog: + title: "确认对话框" + content: "目前有搭子课表数据,是否要覆盖?" + login_message: "登录中,暂时显示缓存数据" + successful_login_message: "登录成功" + password_wrong_dialog: + title: "用户名或密码有误" + content: "是否重启应用后手动登录?" + confirm: "确认" + denial: "否,进入离线模式" + offline_mode_dialog: + title: 统一认证服务离线模式开启 + content: 无法连接到统一认证服务服务器,所有和其相关的服务暂时不可用。 + 成绩查询,考试信息查询,欠费查询,校园卡查询关闭。课表显示缓存数据。其他功能暂不受影响。 + 如有不便,敬请谅解。 + message: "脱机模式下,一站式相关功能全部禁止使用" + notice_card: + empty_notice: "目前没有获取应用公告,请刷新" + no_notice_avaliable: "没有获取应用公告" + notice_list_title: "应用信息" + open_url: "访问该链接" + notice_page_title: "通知列表" + class_table_card: + current: "当前" + tomorrow: "明天" + later: "稍后" + more: "更多" + error_message: "遇到错误:{error}" + fetching_message: "正在获取课表" + error_infoText: "遇到错误" + fetching_infoText: "正在加载" + no_arrangement_infoText: "暂无日程" + electricity_card: + title: "电量信息" + current_electricity: "目前电量 " + kwh: " 度" + dialog: + title: "水电信息" + content: 电费帐号:{account} + 电量信息:{electricityInfo.value} + {electricityInfo} + 欠费信息:{owe_value} + 长按可以重新加载,有欠费一般代表水费 + confirm: "确定" + library_card: + title: "图书借阅" + current_borrow: "目前借书 " + unit_of_book: " 本" + error_occured: "获取借书信息发生错误" + fetching: "正在获取借书信息" + no_return: "目前没有待归还书籍" + need_return: "待归还{borrow_info.dued}本书籍" + no_info: "目前无法获取信息" + fetching_info: "正在查询信息中" + school_card_info_card: + error_toast: "遇到错误,请联系开发者" + fetching_toast: "正在获取信息,请稍后再来看" + bill: "流水" + balance: "校园卡余额 " + unit: " 元" + error_occured: "获取校园卡信息发生错误" + fetching: "正在获取校园卡信息" + bottom_text_success: "查询一卡通流水" + no_info: "目前无法获取信息" + fetching_info: "正在查询信息中" + toolbox: + creative: "双创竞赛" + empty_classroom: "空闲教室" + exam: "考试安排" + experiment: "物理实验" + score: "成绩查询" + sport: "体育信息" + toolbox: "其他功能" + score_cannot_reach: "脱机状态且无缓存成绩数据,无法访问" + exam_fetching: "请稍候,正在获取考试信息" + exam_error: "遇到错误,请联系开发者" + +# 图书馆 +library: + title: "图书馆信息" + borrow_state_title: "借书状态" + search_book_title: "查询藏书" + not_provided: "没有相关信息" + author: "作者 " + publish_house: "出版社 " + call_number: "索书号 " + publish_date: "发行时间 " + isbn: "ISBN" + arrangement_code: "编排号码 " + avaliable_borrow: "可借" + storage: "馆藏" + on_shelve: "在架" + book_code: "书籍编号:{barCode}" + due_date: " 到期" + borrow_str: " 借阅" + after_due_date: " 天前到期" + before_due_date: " 天后" + can_be_renewable: "续借" + cannot_be_renewable: "不可续借" + renewing: "正在续借" + empty_borrow_list: "目前没有查询到在借图书\n不借书就要变成上面的小呆瓜咯" + borrow_list_info: "在借 {borrowListLength} 本,其中已过期 {duedLength} 本" + search_book_window: + search_here: "在此搜索" + book_detail: "书籍详细信息" + no_result: "没有结果" + please_search: "请在上面搜索框搜索" + +# 校园卡流水 +school_card_window: + title: "校园卡流水信息" + income: "支出 {income}" + expense: "收入 {expense}" + select_range: "选择日期:从 {startDay} 到 {endDay}" + store_name: "商户名称" + balance: "金额" + time_with_sum: "时间(共{sum}元)" + +# 成绩 +score: + title: "成绩查询" + cache_message: "已显示缓存成绩信息" + # TODO:string in eval detected + all_semester: "所有学期" + chosen_semester: "学期 {chosen}" + all_type: "所有类型" + chosen_type: "类型 {type}" + score_choice: + title: "成绩单" + search_hint: "搜索成绩记录" + empty_list: "没有选择该学期的课程计入均分计算" + sum_dialog: + title: "小总结" + content: 所有科目的GPA:{gpa_all} + 所有科目的均分:{avg_all} + 所有科目的学分:{credit_all} + 未通过科目:{unpassed} + 公共选修课已经修得学分:{not_core_credit} + 本程序提供的数据仅供参考,开发者对其准确性不负责 + score_compose_card: + no_detail: "未提供详情信息" + fetching: "正在获取" + credit: "学分" + gpa: "GPA" + score: "成绩" + score_info_card: + title: "成绩详情" + original_course: "初修" + failed: "[挂] " + credit: "学分 {credit}" + gpa: "GPA {gpa}" + score: "成绩 {score}" + score_page: + title: "成绩查询" + search_hint: "搜索成绩记录" + no_record: "未筛查到合请求的记录" + select_all: "全选" + select_nothing: "全不选" + reset_select: "重置选择" + # 也许没用 + CET-4: "国家英语四级" + CET-6: "国家英语六级" + +# 设置 +setting: + # 最顶部 + about: "关于" + about_this_program: "关于本程序" + version: "版本号:{version_code}" + user_info: "用户信息" + # 界面设置 + ui_setting: "界面设置" + brightness_setting: "设置深浅色" + simplify_timeline: "简化日程时间轴" + simplify_timeline_description: "没有日程时 减少空间占用" + # 账号设置 + account_setting: "界面设置" + sport_password_setting: "体育系统密码设置" + experiment_password_setting: "物理实验系统密码设置" + electricity_password_setting: "电费帐号密码设置" + electricity_password_description: "非 123456 请设置" + # 课表相关设置 + classtable_setting: "课表相关设置" + background: "开启课表背景图" + no_background: "你先选个图片罢,就在下面" + choose_background: "课表背景图选择" + no_permission: "未获取存储权限,无法读取文件" + successful_setting: "设定成功" + failure_setting: "你没有选图片捏" + clear_user_class: "清除所有用户添加课程" + clear_user_class_dialog: + title: "确认对话框" + content: "是否要清除所有用户添加课程?这个功能对从学校获取的日程没有影响。" + clear: "已经清除完毕" + class_refresh: "强制刷新课表" + class_refresh_dialog: + title: "确认对话框" + content: "是否要强制刷新课表?同意后,将会从学校一站式后端重新获取课表,耗时会比较久。" + class_swift: "课程偏移设置" + class_swift_description: "正数错后开学日期 负数提前开学日期\n目前为 {swift}" + # 缓存登录设置 + core_setting: "缓存登录设置" + check_catcher: "测试错误拦截器" + check_logger: "查看网络拦截器和日志" + clear_and_restart: "清除缓存后重启" + clear_and_restart_dialog: + title: "确认对话框" + content: "确定清除缓存后重启程序?" + cleaning: "正在清理缓存" + clear: "缓存已被清除" + logout: "退出登录并重启应用" + logout_dialog: + title: "确认对话框" + content: "确定退出登录?你的所有数据将会被彻底删除!" + logging_out: "正在退出登录" + need_close_dialog: + title: "请关闭应用" + need_restart_d: "因为技术限制,用户需要自行关闭窗口,然后重新打开应用。" + # 剩下乱七八糟的窗口 + change_brightness_dialog: + title: "颜色设置" + follow_setting: "跟随系统" + day_mode: "白天模式" + night_mode: "黑夜模式" + change_swift_dialog: + title: "课程偏移设置" + input_hint: "请在此输入数字" + change_password_dialog: + title: "修改电费帐号密码" + input_hint: "请在此输入密码" + blank_input: "输入空白!" + easter_egg_page: + title: "你找到了彩蛋" + encrypt: "加密上面的文本" + listen: "听歌时间" + about_page: + benderblog: "主要开发者,iOS 小部件编写和拼接" + bellssgit: "支持:最佳&最久故障反馈者" + brackrat: "设计:主页,登录页,配色,iOS 小部件等" + breezeline: "支持:无价值无意义的产品经理(他自己的描述)" + cafebabe: “支持:提供彩蛋代码" + chitao1234: "开发:修复滑块不对齐问题" + dimole: "支持:辅助修复滑块问题" + elitewars: "设计:体育成绩页面" + hhzm: "支持:提供彩蛋代码" + lsy223622: "设计:iOS 图标" + nancuncloud: "开发:图书馆搜索功能" + pairman: "开发:成绩缓存功能和优化滑块算法" + reverierxu: "设计:用于信息展示的 ReX 卡片" + ray: "设计:开屏画面 / 支持:iOS 开发" + stalomeow: "设计:首页时间轴 / 开发:异步登录" + xeonds: "设计:设置页面 / 开发:XDU Planet" + xiue233: "开发:Android 小部件和拼接" + zcwzy: "开发:修复丁香电费 / 支持:研究生版本开发" + homepage: "主页" + code: "开源代码" + donate: "给我捐款" + know_more: "知道更多" + copyright_notice: + 本软件拷贝基于 traintime_pda 代码(或称 watermeter 代码)编译, + 代码按照 Mozilla Public License, v. 2.0 授权。 + 本程序和西安电子科技大学,体适能服务,书蜗,电表等服务无关。 + Copyright 2023-Present BenderBlog Rodriguez and contributors. + The Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. + If a copy of the MPL was not distributed with this file, + You can obtain one at https://mozilla.org/MPL/2.0/. + beian: "备案号" + sign_android: "安卓签名" + title: "关于本软件" + +# 体育查询 +sport: + fetching: "正在获取" + error: "坏事: {situation}" + title: "体育查询" + class_info: "课程信息" + test_score: "体测成绩" + # TODO: change sport score to support i18n + total_score: "四年总分" + semester: "{year} 第{gradeType}" + subject: "项目" + data: "数据" + score: "分数" + passed: "及格" + score_string: "{score}分" + +# 其他功能 +toolbox: + title: "其他功能" + payment: "缴费系统" + payment_description: "电费该交了吧" + repair: "后勤报修" + repair_description: "不要漏水断网" + reserve: "空间预约" + reserve_description: "找个地方打牌" + mobile: "移动门户" + mobile_description: "请假专用门户" + network: "网络查询" + network_description: "希望永不收费" + physics: "物理计算" + physics_description: "希望操作顺利" + discover: "睿思导航" + discover_description: "补充其他功能" + +# XDU Planet +xdu_planet: + # TODO:string in eval detected + all: "全部" + loading: "加载中,请稍等 <(=ω=)>" + unknown_author: "未知作者" + load_failed: "文章加载失败,如有需要可以点击右上方的按钮在浏览器里打开。" + no_comment: "暂无评论" + reply_audit: "回复评论 #{reply_to} 已被举报或删除" + reply: "回复评论 #{reply_to}:{content}" + have_been_audit: "本评论已经被举报" + audit: "举报" + confirm_audit_dialog: + title: "确认是否举报" + content: "三思而后行,确定您想举报吗?举报后该评论会有标签,不一定会删除。" + ongoing: "正在举报评论" + failed: "举报失败" + success: "举报成功" + comment: "回复" + comment_success: "评论成功" + comment_failed: "评论失败,请去网络查看器和日志查看器查看报错" + comment_canceled: "没想好要说啥嘛" + comment_loading: "加载评论中……" diff --git a/lib/main.dart b/lib/main.dart index 7e38c0cd..e3df44b1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'dart:ui'; import 'package:catcher_2/catcher_2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:watermeter/repository/logger.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -103,7 +104,19 @@ class _MyAppState extends State { Widget build(BuildContext context) { return GetBuilder( builder: (c) => MaterialApp( - localizationsDelegates: const [ + localizationsDelegates: [ + FlutterI18nDelegate( + translationLoader: FileTranslationLoader( + fallbackFile: "zh_CN", + useCountryCode: true, + ), + missingTranslationHandler: (key, locale) { + log.info( + "--- Missing Key: $key, " + "languageCode: ${locale?.languageCode ?? "unknown"}", + ); + }, + ), GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, diff --git a/lib/page/homepage/home.dart b/lib/page/homepage/home.dart index 82e22ce5..5b717e7f 100644 --- a/lib/page/homepage/home.dart +++ b/lib/page/homepage/home.dart @@ -132,100 +132,99 @@ class _HomePageMasterState extends State log.info("Partner File Position: ${value.first.path}"); final c = Get.find(); - if (c.state == ClassTableState.fetched) { - File file = - File("${supportPath.path}/${ClassTableFile.partnerClassName}"); - - log.info( - "Partner file exists: " - "${file.existsSync()}", + if (c.state != ClassTableState.fetched) { + showToast( + context: context, + msg: "还没加载课程表,等会再来吧……", ); + return; + } + File file = + File("${supportPath.path}/${ClassTableFile.partnerClassName}"); + + log.info( + "Partner file exists: " + "${file.existsSync()}", + ); - if (file.existsSync()) { - bool? confirm = await showDialog( + if (file.existsSync()) { + bool? confirm = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text("确认对话框"), + content: const Text("目前有搭子课表数据,是否要覆盖?"), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: const Text("取消"), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: const Text("确定"), + ) + ], + ), + ); + if (context.mounted && confirm != true) { + return; + } + } + String source = ""; + try { + if (Platform.isAndroid && value.first.path.startsWith("content://")) { + Content content = + await ContentResolver.resolveContent(value.first.path); + source = utf8.decode(content.data.toList()); + } else { + source = + File.fromUri(Uri.parse(value.first.path)).readAsStringSync(); + } + } catch (e) { + if (mounted) { + showToast( context: context, - builder: (context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text("目前有搭子课表数据,是否要覆盖?"), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: const Text("取消"), - ), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: const Text("确定"), - ) - ], - ), + msg: '导入文件失败', ); - if (context.mounted && confirm != true) { - return; - } - } - String source = ""; - try { - if (Platform.isAndroid && - value.first.path.startsWith("content://")) { - Content content = - await ContentResolver.resolveContent(value.first.path); - source = utf8.decode(content.data.toList()); - } else { - source = - File.fromUri(Uri.parse(value.first.path)).readAsStringSync(); - } - } catch (e) { - if (mounted) { - showToast( - context: context, - msg: '导入文件失败', - ); - log.error("Import partner classtable error.", e); - return; - } + log.error("Import partner classtable error.", e); + return; } + } - if (mounted) { - try { - final data = jsonDecode(source); + if (mounted) { + try { + final data = jsonDecode(source); - String semesterCode = Get.put( - ClassTableController(), - ).classTableData.semesterCode; + String semesterCode = Get.put( + ClassTableController(), + ).classTableData.semesterCode; - if (semesterCode.compareTo( - data["classtable"]["semesterCode"].toString()) != - 0) { - throw NotSameSemesterException( - msg: "Not the same semester. This semester: $semesterCode. " - "Input source: ${data["classtable"]["semesterCode"]}." - "This partner classtable is going to be deleted.", - ); - } - File( - "${supportPath.path}/${ClassTableFile.partnerClassName}", - ).writeAsStringSync(source); - } catch (error, stacktrace) { - log.error( - "Error occured while importing partner class.", - error, - stacktrace, - ); - showToast( - context: context, - msg: '好像导入文件有点问题:P', + if (semesterCode + .compareTo(data["classtable"]["semesterCode"].toString()) != + 0) { + throw NotSameSemesterException( + msg: "Not the same semester. This semester: $semesterCode. " + "Input source: ${data["classtable"]["semesterCode"]}." + "This partner classtable is going to be deleted.", ); - return; } + File( + "${supportPath.path}/${ClassTableFile.partnerClassName}", + ).writeAsStringSync(source); + } catch (error, stacktrace) { + log.error( + "Error occured while importing partner class.", + error, + stacktrace, + ); showToast( context: context, - msg: '导入成功,如果打开了课表页面请重新打开', + msg: '好像导入文件有点问题:P', ); + return; } - } else { showToast( context: context, - msg: "还没加载课程表,等会再来吧……", + msg: '导入成功,如果打开了课表页面请重新打开', ); } diff --git a/lib/repository/xidian_ids/library_session.dart b/lib/repository/xidian_ids/library_session.dart index 8a9a12c6..7148cf06 100644 --- a/lib/repository/xidian_ids/library_session.dart +++ b/lib/repository/xidian_ids/library_session.dart @@ -203,7 +203,8 @@ class LibrarySession extends IDSSession { ).then((value) => jsonDecode(value.data)); if (!isSuccess["status"]) { - throw NotFetchLibraryException(message: "登陆失败: ${isSuccess["status"]}"); + throw NotFetchLibraryException( + message: "Login failed: ${isSuccess["status"]}"); } response = await dio.get(destinationURL, queryParameters: { @@ -240,5 +241,5 @@ class LibrarySession extends IDSSession { class NotFetchLibraryException implements Exception { final String message; - NotFetchLibraryException({this.message = "发生错误"}); + NotFetchLibraryException({this.message = "Error detected."}); } diff --git a/pubspec.lock b/pubspec.lock index a1e650d5..89581f6f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -454,6 +454,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" + flutter_i18n: + dependency: "direct main" + description: + name: flutter_i18n + sha256: "37334bfabd05655895dc0c90a38022e4e588eefb848ffc9d382f37439a44be46" + url: "https://pub.dev" + source: hosted + version: "0.36.2" flutter_launcher_icons: dependency: "direct dev" description: @@ -1387,6 +1395,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + toml: + dependency: transitive + description: + name: toml + sha256: "9968de24e45b632bf1a654fe1ac7b6fe5261c349243df83fd262397799c45a2d" + url: "https://pub.dev" + source: hosted + version: "0.15.0" tuple: dependency: transitive description: @@ -1595,6 +1611,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.5.0" + xml2json: + dependency: transitive + description: + name: xml2json + sha256: dbe79a85d902674d95c7608c8048355ce2ec5846640da1c0f91389ccdad5b5a8 + url: "https://pub.dev" + source: hosted + version: "6.2.4" yaml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 05d0750a..3a35895c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,9 +46,6 @@ dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 - flutter_localizations: - sdk: flutter - intl: package_info_plus: ^8.0.0 flutter_markdown: ^0.7.2 flutter_svg: ^2.0.10+1 @@ -77,8 +74,14 @@ dependencies: fwfh_url_launcher: ^0.9.1 latext: ^0.4.1 permission_handler: ^11.3.1 + # internationalized device_info_plus: ^10.1.2 + flutter_i18n: ^0.36.2 + flutter_localizations: + sdk: flutter + intl: + dev_dependencies: flutter_test: sdk: flutter @@ -109,4 +112,5 @@ flutter: - assets/Empty-Cover.jpg - assets/icon.png - assets/CP1919.svg.vec - - assets/Icon-App-iTunes-Background.png \ No newline at end of file + - assets/Icon-App-iTunes-Background.png + - assets/flutter_i18n \ No newline at end of file From 437887ad1a1758222cfd8c77b8c17cbf6ab1ee0d Mon Sep 17 00:00:00 2001 From: "BenderBlog \"SuperBart\" Rodriguez" Date: Sun, 6 Oct 2024 00:41:40 +0800 Subject: [PATCH 2/4] feat: sync classtable to i18n --- assets/flutter_i18n/zh_CN.yaml | 35 ++-- .../course_detail_card.dart | 50 +++-- .../class_add/class_add_window.dart | 91 ++++++--- .../class_page/class_change_list.dart | 109 +++++++---- .../class_page/classtable_page.dart | 173 ++++++++++++++---- .../class_page/empty_classtable_page.dart | 17 +- .../class_page/not_arranged_class_list.dart | 25 ++- .../class_page/week_choice_view.dart | 9 +- .../class_table_view/class_card.dart | 19 +- .../class_organized_data.dart | 2 +- .../class_table_view/class_table_view.dart | 19 +- .../class_table_view/classtable_date_row.dart | 2 +- lib/page/classtable/classtable_constant.dart | 27 ++- lib/page/homepage/toolbox/creative_card.dart | 2 +- .../toolbox/empty_classroom_card.dart | 2 +- lib/page/homepage/toolbox/exam_card.dart | 2 +- .../homepage/toolbox/experiment_card.dart | 2 +- lib/page/homepage/toolbox/score_card.dart | 2 +- .../homepage/toolbox/small_function_card.dart | 10 +- lib/page/homepage/toolbox/sport_card.dart | 2 +- lib/page/homepage/toolbox/toolbox_card.dart | 2 +- pubspec.yaml | 6 +- 22 files changed, 429 insertions(+), 179 deletions(-) diff --git a/assets/flutter_i18n/zh_CN.yaml b/assets/flutter_i18n/zh_CN.yaml index 24f6920d..64a7216c 100644 --- a/assets/flutter_i18n/zh_CN.yaml +++ b/assets/flutter_i18n/zh_CN.yaml @@ -1,3 +1,6 @@ +# Copyright 2024 BenderBlog Rodriguez and contributors. +# SPDX-License-Identifier: MPL-2.0 + # EasyRefresh 下拉插件的玩意 drag_text: "上拉请求更多" ready_text: "正在加载......" @@ -12,6 +15,7 @@ error_detected: "Ouch! 发生错误啦" click_to_refresh: "点我刷新" # 取消和确定 +confirm_title: "确认对话框" cancel: "取消" confirm: "确定" @@ -78,17 +82,14 @@ classtable: saturday: "周六" sunday: "周日" partner_classtable: - override_dialog: - title: "确认对话框" - message: "目前有搭子课表数据,是否要覆盖?" - message: - no_file: "未发现导入文件" - no_permission: "未获取存储权限,无法读取文件" - problem: "好像导入文件有点问题:P" - success: "导入成功" + override_dialog: "目前有搭子课表数据,是否要覆盖?" + no_file: "未发现导入文件" + no_permission: "未获取存储权限,无法读取文件" + problem: "好像导入文件有点问题:P" + success: "导入成功" share_dialog: title: "请不要随意分享" - hint: "导出文件包括你的个人信息,请不要随意跟别人分享,或者发在大群里。" + content: "导出文件包括你的个人信息,请不要随意跟别人分享,或者发在大群里。" save_dialog: title: "保存日历文件到..." success_message: "应该保存成功" @@ -112,6 +113,13 @@ classtable: empty_message: "目前没有调课信息" teacher_change: "从{previous_teacher}变为{new_teacher}" no_teacher_change: "教师信息没有改变" + 1: '一' + 2: '二' + 3: '三' + 4: '四' + 5: '五' + 6: '六' + 7: '日' change_class_message: 调课信息,从第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}节 调整为第{newAffectedWeeksListStr}周星期{weekChar_newWeek}的 @@ -122,7 +130,7 @@ classtable: stop_class_message: 停课信息,第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}节 {originalClassroom}停课 - class_info: "编号: {classCode} | {classNumber} 班\n安排变更:{classChange}" + class_info: "编号: {classCode} | {classNumber} 班\n安排变更:{classChange}\n{teacherChange}" not_arranged_page: title: "没有时间安排的科目" empty_message: "目前全部课程均有时间安排" @@ -154,12 +162,11 @@ classtable: class_number_string: "{number} 班" unknown_teacher: "老师未定" unknown_place: "地点未定" - class_period: "{start}-${stop}节" + class_period: "{start}-{stop}节" edit: "编辑" delete: "删除" - delete_confirm_dialog: - title: "是否删除课程信息?" - content: "所有关于这个课的信息都会被删除,课表上关于这门课的信息将不复存在!" + delete_title: "是否删除课程信息?" + delete_content: "所有关于这个课的信息都会被删除,课表上关于这门课的信息将不复存在!" # 双创信息 creative_job: diff --git a/lib/page/classtable/arrangement_detail/course_detail_card.dart b/lib/page/classtable/arrangement_detail/course_detail_card.dart index 58bb0cf3..d3d0721c 100644 --- a/lib/page/classtable/arrangement_detail/course_detail_card.dart +++ b/lib/page/classtable/arrangement_detail/course_detail_card.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 OR Apache-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/classtable.dart'; import 'package:watermeter/page/classtable/class_add/class_add_window.dart'; @@ -77,7 +78,13 @@ class ClassDetailCard extends StatelessWidget { children: [ Text( "${classDetail.name}" - "${classDetail.code != null && classDetail.number != null ? "\n${classDetail.code} | ${classDetail.number} 班" : ""}", + "${classDetail.code != null && classDetail.number != null ? "\n${classDetail.code} | ${FlutterI18n.translate( + context, + "classtable.course_detail_card.class_number_string", + translationParams: { + "number": classDetail.number.toString(), + }, + )}" : ""}", style: TextStyle( color: infoColor.shade900, fontSize: 18, @@ -90,14 +97,22 @@ class ClassDetailCard extends StatelessWidget { Flexible( child: CustomListTile( icon: Icons.person, - str: timeArrangement.teacher ?? "老师未定", + str: timeArrangement.teacher ?? + FlutterI18n.translate( + context, + "classtable.course_detail_card.unknown_teacher", + ), infoColor: infoColor, ), ), Flexible( child: CustomListTile( icon: Icons.room, - str: timeArrangement.classroom ?? "地点未定", + str: timeArrangement.classroom ?? + FlutterI18n.translate( + context, + "classtable.course_detail_card.unknown_place", + ), infoColor: infoColor, ), ), @@ -105,8 +120,11 @@ class ClassDetailCard extends StatelessWidget { ), CustomListTile( icon: Icons.access_time_filled_outlined, - str: "${weekList[timeArrangement.day - 1]}" - "${timeArrangement.start}-${timeArrangement.stop}节 " + str: "${getWeekString(context, timeArrangement.day - 1)}" + "${FlutterI18n.translate(context, "classtable.course_detail_card.class_period", translationParams: { + "start": timeArrangement.start.toString(), + "stop": timeArrangement.stop.toString(), + })} " "${time[(timeArrangement.start - 1) * 2]}-${time[(timeArrangement.stop - 1) * 2 + 1]}", infoColor: infoColor, ), @@ -143,7 +161,10 @@ class ClassDetailCard extends StatelessWidget { ); }, child: Text( - "编辑", + FlutterI18n.translate( + context, + "classtable.course_detail_card.edit", + ), style: TextStyle( color: infoColor.shade900, ), @@ -153,10 +174,14 @@ class ClassDetailCard extends StatelessWidget { bool? isContinue = await showDialog( context: context, builder: (context) => AlertDialog( - title: const Text("是否删除课程信息?"), - content: const Text( - "所有关于这个课的信息都会被删除,课表上关于这门课的信息将不复存在!", - ), + title: Text(FlutterI18n.translate( + context, + "classtable.course_detail_card.delete_title", + )), + content: Text(FlutterI18n.translate( + context, + "classtable.course_detail_card.delete_content", + )), actions: [ TextButton( style: TextButton.styleFrom( @@ -186,7 +211,10 @@ class ClassDetailCard extends StatelessWidget { } }, child: Text( - "删除", + FlutterI18n.translate( + context, + "classtable.course_detail_card.delete", + ), style: TextStyle( color: infoColor.shade900, ), diff --git a/lib/page/classtable/class_add/class_add_window.dart b/lib/page/classtable/class_add/class_add_window.dart index 5fa68174..3f3d5688 100644 --- a/lib/page/classtable/class_add/class_add_window.dart +++ b/lib/page/classtable/class_add/class_add_window.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 OR Apache-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/classtable.dart'; @@ -93,19 +94,33 @@ class _ClassAddWindowState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(widget.toChange == null ? "添加课程" : "修改课程"), + title: Text(widget.toChange == null + ? FlutterI18n.translate( + context, + "classtable.class_add.add_class_title", + ) + : FlutterI18n.translate( + context, + "classtable.class_add.change_class_title", + )), actions: [ TextButton( onPressed: () async { if (classNameController.text.isEmpty) { showToast( context: context, - msg: "必须输入课程名", + msg: FlutterI18n.translate( + context, + "classtable.class_add.class_name_empty_message", + ), ); } else if (!(week > 0 && week <= 7) || !(start <= stop)) { showToast( context: context, - msg: "输入的时间不对", + msg: FlutterI18n.translate( + context, + "classtable.class_add.wrong_time_message", + ), ); } else if (widget.toChange == null) { await controller @@ -152,7 +167,10 @@ class _ClassAddWindowState extends State { }); } }, - child: const Text("保存"), + child: Text(FlutterI18n.translate( + context, + "classtable.class_add.save_button", + )), ), ], ), @@ -170,7 +188,10 @@ class _ClassAddWindowState extends State { Icons.calendar_month, color: color, ), - hintText: "课程名字(必填)", + hintText: FlutterI18n.translate( + context, + "classtable.class_add.input_classname_hint", + ), ), ).padding(vertical: inputFieldVerticalPadding), TextField( @@ -180,7 +201,10 @@ class _ClassAddWindowState extends State { Icons.person, color: color, ), - hintText: "老师姓名(选填)", + hintText: FlutterI18n.translate( + context, + "classtable.class_add.input_teacher_hint", + ), ), ).padding(vertical: inputFieldVerticalPadding), TextField( @@ -190,7 +214,10 @@ class _ClassAddWindowState extends State { Icons.place, color: color, ), - hintText: "教室位置(选填)", + hintText: FlutterI18n.translate( + context, + "classtable.class_add.input_classroom_hint", + ), ), ).padding(vertical: inputFieldVerticalPadding), ], @@ -215,9 +242,10 @@ class _ClassAddWindowState extends State { color: color, size: 16, ), - const Text("选择上课周次") - .textStyle(TextStyle(color: color)) - .padding(left: 4), + Text(FlutterI18n.translate( + context, + "classtable.class_add.input_week_hint", + )).textStyle(TextStyle(color: color)).padding(left: 4), ], ), const SizedBox(height: 8), @@ -250,9 +278,10 @@ class _ClassAddWindowState extends State { color: color, size: 16, ), - const Text("选择上课时间") - .textStyle(TextStyle(color: color)) - .padding(left: 4), + Text(FlutterI18n.translate( + context, + "classtable.class_add.input_time_hint", + )).textStyle(TextStyle(color: color)).padding(left: 4), ], ), const SizedBox(height: 8), @@ -260,18 +289,18 @@ class _ClassAddWindowState extends State { children: [ Row( children: [ - const Text("上课周次") - .textStyle(TextStyle(color: color)) - .center() - .flexible(), - const Text("上课时间段") - .textStyle(TextStyle(color: color)) - .center() - .flexible(), - const Text("下课时间段") - .textStyle(TextStyle(color: color)) - .center() - .flexible(), + Text(FlutterI18n.translate( + context, + "classtable.class_add.input_time_weekday_hint", + )).textStyle(TextStyle(color: color)).center().flexible(), + Text(FlutterI18n.translate( + context, + "classtable.class_add.input_start_time_hint", + )).textStyle(TextStyle(color: color)).center().flexible(), + Text(FlutterI18n.translate( + context, + "classtable.class_add.input_end_time_hint", + )).textStyle(TextStyle(color: color)).center().flexible(), ], ), Row( @@ -284,10 +313,10 @@ class _ClassAddWindowState extends State { }, defaultPage: week - 1, options: List.generate( - weekList.length, + 7, (index) => WheelChooseOptions( data: index, - hint: weekList[index], + hint: getWeekString(context, index), ), ), ).flexible(), @@ -317,7 +346,13 @@ class _ClassAddWindowState extends State { 10, (index) => WheelChooseOptions( data: index + 1, - hint: "第 ${index + 1} 节", + hint: FlutterI18n.translate( + context, + "classtable.class_add.wheel_choose_hint", + translationParams: { + "index": (index + 1).toString() + }, + ), ), ), ).flexible() diff --git a/lib/page/classtable/class_page/class_change_list.dart b/lib/page/classtable/class_page/class_change_list.dart index 3da1e89a..b40983c3 100644 --- a/lib/page/classtable/class_page/class_change_list.dart +++ b/lib/page/classtable/class_page/class_change_list.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 OR Apache-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/classtable.dart'; import 'package:watermeter/page/classtable/classtable_state.dart'; @@ -22,11 +23,19 @@ class ClassChangeList extends StatelessWidget { return Scaffold( appBar: AppBar( - title: const Text("课程调整"), + title: Text(FlutterI18n.translate( + context, + "classtable.class_change_page.title", + )), ), body: Builder(builder: (context) { if (classChanges.isEmpty) { - return const EmptyListView(text: "目前没有调课信息"); + return EmptyListView( + text: FlutterI18n.translate( + context, + "classtable.class_change_page.empty_message", + ), + ); } return ListView.builder( @@ -38,11 +47,18 @@ class ClassChangeList extends StatelessWidget { if (classChanges[index].type != ChangeType.stop) { if (toShow.isTeacherChanged && classChanges[index].newTeacher != null) { - teacherChange += - "从${classChanges[index].originalTeacher ?? "没有信息"}" - "变为${classChanges[index].originalNewTeacher}"; + teacherChange += FlutterI18n.translate( + context, "classtable.class_change_page.teacher_change", + translationParams: { + "previous_teacher": + classChanges[index].originalTeacher ?? "没有信息", + "new_teacher": classChanges[index].originalNewTeacher!, + }); } else { - teacherChange += "没有改变"; + teacherChange += FlutterI18n.translate( + context, + "classtable.class_change_page.no_teacher_change", + ); } } @@ -66,50 +82,71 @@ class ClassChangeList extends StatelessWidget { } } - String chineseWeekChar(int? week) { - switch (week) { - case 1: - return '一'; - case 2: - return '二'; - case 3: - return '三'; - case 4: - return '四'; - case 5: - return '五'; - case 6: - return '六'; - case 7: - return '日'; - default: - return ' '; - } - } + String weekChar(int? week) => FlutterI18n.translate( + context, + week != null ? "classtable.class_change_page.$week" : "", + ); String classChange = ""; switch (toShow.type) { case ChangeType.change: - classChange += - "调课信息,从第$originalAffectedWeeksStr周星期${chineseWeekChar(toShow.originalWeek)}的${toShow.originalClassRange[0]}-${toShow.originalClassRange[1]}节" - "调整为第$newAffectedWeeksListStr周星期${chineseWeekChar(toShow.newWeek)}的${toShow.newClassRange[0]}-${toShow.newClassRange[1]}节,${toShow.newClassroom}教室上课"; + classChange += FlutterI18n.translate(context, + "classtable.class_change_page.change_class_message", + translationParams: { + "originalAffectedWeeks": originalAffectedWeeksStr, + "weekChar_originalWeek": weekChar(toShow.originalWeek), + "originalClassRangeStart": + toShow.originalClassRange[0].toString(), + "originalClassRangeEnd": + toShow.originalClassRange[1].toString(), + "newAffectedWeeksListStr": newAffectedWeeksListStr, + "weekChar_newWeek": weekChar(toShow.newWeek), + "newClassRangeStart": + toShow.newClassRange[0].toString(), + "newClassRangeStop": toShow.newClassRange[1].toString(), + "newClassroom": toShow.newClassroom.toString(), + }); break; case ChangeType.patch: - classChange += - "补课信息,从第$newAffectedWeeksListStr周星期${chineseWeekChar(toShow.newWeek)}的${toShow.newClassRange[0]}-${toShow.newClassRange[1]}节,${toShow.newClassroom}补课"; + classChange += FlutterI18n.translate(context, + "classtable.class_change_page.patch_class_message", + translationParams: { + "newAffectedWeeksListStr": newAffectedWeeksListStr, + "weekChar_newWeek": weekChar(toShow.newWeek), + "newClassRangeStart": + toShow.newClassRange[0].toString(), + "newClassRangeStop": toShow.newClassRange[1].toString(), + "newClassroom": toShow.newClassroom.toString(), + }); break; case ChangeType.stop: - classChange += - "停课信息,第$originalAffectedWeeksStr周星期${chineseWeekChar(toShow.originalWeek)}的${toShow.originalClassRange[0]}-${toShow.originalClassRange[1]}节,${toShow.originalClassroom}停课"; + classChange += FlutterI18n.translate(context, + "classtable.class_change_page.stop_class_message", + translationParams: { + "originalAffectedWeeks": originalAffectedWeeksStr, + "weekChar_originalWeek": weekChar(toShow.originalWeek), + "originalClassRangeStart": + toShow.originalClassRange[0].toString(), + "originalClassRangeEnd": + toShow.originalClassRange[1].toString(), + }); break; } return ListTile( title: Text(toShow.className), subtitle: Text( - "编号: ${classChanges[index].classCode} | ${classChanges[index].classNumber} 班\n" - "安排变更:$classChange" - "${classChanges[index].type == ChangeType.change ? "\n老师变更: $teacherChange" : ""}", + FlutterI18n.translate( + context, "classtable.class_change_page.class_info", + translationParams: { + "classCode": classChanges[index].classCode, + "classNumber": classChanges[index].classNumber, + "classChange": classChange, + "teacherChange": + classChanges[index].type == ChangeType.change + ? "老师变更: $teacherChange" + : "", + }), ), ); }).constrained(maxWidth: 600); diff --git a/lib/page/classtable/class_page/classtable_page.dart b/lib/page/classtable/class_page/classtable_page.dart index b7c3964c..7160fd5f 100644 --- a/lib/page/classtable/class_page/classtable_page.dart +++ b/lib/page/classtable/class_page/classtable_page.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:jiffy/jiffy.dart'; import 'package:path_provider/path_provider.dart'; import 'package:watermeter/page/classtable/class_add/class_add_window.dart'; @@ -188,16 +189,22 @@ class _ClassTablePageState extends State { bool? confirm = await showDialog( context: context, builder: (context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text("目前有搭子课表数据,是否要覆盖?"), + title: Text(FlutterI18n.translate( + context, + "confirm_title", + )), + content: Text(FlutterI18n.translate( + context, + "classtable.partner_classtable.override_dialog", + )), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: const Text("取消"), + child: Text(FlutterI18n.translate(context, "cancel")), ), TextButton( onPressed: () => Navigator.of(context).pop(true), - child: const Text("确定"), + child: Text(FlutterI18n.translate(context, "confirm")), ) ], ), @@ -214,11 +221,22 @@ class _ClassTablePageState extends State { if (mounted && result.isEmpty) { showToast( context: context, - msg: '未发现导入文件', + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.no_file", + ), ); } } on MissingStoragePermissionException { - if (mounted) showToast(context: context, msg: "未获取存储权限,无法读取文件"); + if (mounted) { + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.no_permission", + ), + ); + } } if (mounted) { @@ -238,13 +256,19 @@ class _ClassTablePageState extends State { ); showToast( context: context, - msg: '好像导入文件有点问题:P', + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.problem", + ), ); return; } showToast( context: context, - msg: '导入成功', + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.success", + ), ); } } @@ -254,7 +278,15 @@ class _ClassTablePageState extends State { if (haveClass) { return Scaffold( appBar: AppBar( - title: Text(classTableState.isPartner ? "搭子的日程表" : "日程表"), + title: Text(classTableState.isPartner + ? FlutterI18n.translate( + context, + "classtable.partner_page_title", + ) + : FlutterI18n.translate( + context, + "classtable.page_title", + )), leading: IconButton( icon: Icon( Platform.isIOS || Platform.isMacOS @@ -280,34 +312,55 @@ class _ClassTablePageState extends State { PopupMenuButton( itemBuilder: (BuildContext context) => >[ - const PopupMenuItem( + PopupMenuItem( value: 'A', - child: Text("查看未安排课程信息"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.not_arranged", + )), ), - const PopupMenuItem( + PopupMenuItem( value: 'B', - child: Text("查看课程安排调整信息"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.class_changed", + )), ), if (!classTableState.isPartner) ...[ - const PopupMenuItem( + PopupMenuItem( value: 'C', - child: Text("添加课程信息"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.add_class", + )), ), - const PopupMenuItem( + PopupMenuItem( value: 'D', - child: Text("生成日历文件"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.generate_ical", + )), ), - const PopupMenuItem( + PopupMenuItem( value: 'E', - child: Text("生成共享课表文件"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.generate_partner_file", + )), ), - const PopupMenuItem( + PopupMenuItem( value: 'F', - child: Text("导入共享课表文件"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.import_partner_file", + )), ), - const PopupMenuItem( + PopupMenuItem( value: 'G', - child: Text("删除共享课表文件"), + child: Text(FlutterI18n.translate( + context, + "classtable.popup_menu.delete_partner_file", + )), ), ], ], @@ -347,9 +400,14 @@ class _ClassTablePageState extends State { await showDialog( context: context, builder: (context) => AlertDialog( - title: const Text("请不要随意分享"), - content: const Text( - "导出文件包括你的个人信息,请不要随意跟别人分享,或者发在大群里。"), + title: Text(FlutterI18n.translate( + context, + "classtable.partner_classtable.share_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "classtable.partner_classtable.share_dialog.content", + )), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), @@ -367,12 +425,17 @@ class _ClassTablePageState extends State { fileName += "-${preference.getString(preference.Preference.idsAccount)}.erc"; } - if (Platform.isLinux || - Platform.isMacOS || - Platform.isWindows) { + if ((Platform.isLinux || + Platform.isMacOS || + Platform.isWindows) && + context.mounted) { + String title = FlutterI18n.translate( + context, + "classtable.partner_classtable.save_dialog.title", + ); String? resultFilePath = await FilePicker.platform.saveFile( - dialogTitle: "保存日历文件到...", + dialogTitle: title, fileName: fileName, allowedExtensions: [ if (action == 'D') "ics" else "erc" @@ -413,11 +476,23 @@ class _ClassTablePageState extends State { await file.delete(); } if (context.mounted) { - showToast(context: context, msg: "应该保存成功"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.save_dialog.success_message", + ), + ); } } on FileSystemException { if (context.mounted) { - showToast(context: context, msg: "文件创建失败,保存取消"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.save_dialog.failure_message", + ), + ); } } break; @@ -427,18 +502,34 @@ class _ClassTablePageState extends State { bool? isDelete = await showDialog( context: context, builder: (context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text("确定要清除共享课表吗?"), + title: Text(FlutterI18n.translate( + context, + "classtable.partner_classtable.delete_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "classtable.partner_classtable.delete_dialog.message", + )), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), - child: const Text("取消"), + child: Text( + FlutterI18n.translate( + context, + "cancel", + ), + ), ), TextButton( onPressed: () => Navigator.of(context).pop(true), - child: const Text("确定"), + child: Text( + FlutterI18n.translate( + context, + "confirm", + ), + ), ) ], ), @@ -448,7 +539,10 @@ class _ClassTablePageState extends State { classTableState.deletePartnerClass(); showToast( context: context, - msg: '删除共享课表成功', + msg: FlutterI18n.translate( + context, + "classtable.partner_classtable.delete_dialog.success_message", + ), ); } } @@ -478,7 +572,10 @@ class _ClassTablePageState extends State { } else { return Scaffold( appBar: AppBar( - title: const Text("日程表"), + title: Text(FlutterI18n.translate( + context, + "classtable.partner_classtable.page_title", + )), leading: IconButton( icon: Icon( Platform.isIOS || Platform.isMacOS diff --git a/lib/page/classtable/class_page/empty_classtable_page.dart b/lib/page/classtable/class_page/empty_classtable_page.dart index a612a744..0c9890b7 100644 --- a/lib/page/classtable/class_page/empty_classtable_page.dart +++ b/lib/page/classtable/class_page/empty_classtable_page.dart @@ -2,20 +2,17 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; -import 'package:watermeter/page/classtable/classtable_state.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/empty_list_view.dart'; class EmptyClasstablePage extends StatelessWidget { const EmptyClasstablePage({super.key}); @override - Widget build(BuildContext context) { - return EmptyListView( - text: "${ClassTableState.of(context)!.controllers.semesterCode} 学期没有课程\n" - "如果刚选完课,过几天就更新了吧\n" - "如果你没选课,快去 xk.xidian.edu.cn\n" - "如果你你要毕业或已经毕业……\n" - "快去关注 SuperBart 哔哩哔哩帐号!", - ); - } + Widget build(BuildContext context) => EmptyListView( + text: FlutterI18n.translate( + context, + "classtable.empty_class_message", + ), + ); } diff --git a/lib/page/classtable/class_page/not_arranged_class_list.dart b/lib/page/classtable/class_page/not_arranged_class_list.dart index 610a61d6..73844f01 100644 --- a/lib/page/classtable/class_page/not_arranged_class_list.dart +++ b/lib/page/classtable/class_page/not_arranged_class_list.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 OR Apache-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/classtable.dart'; import 'package:watermeter/page/classtable/classtable_state.dart'; @@ -19,20 +20,34 @@ class NotArrangedClassList extends StatelessWidget { return Scaffold( appBar: AppBar( - title: const Text("没有时间安排的科目"), + title: Text(FlutterI18n.translate( + context, + "classtable.not_arranged_page.title", + )), ), body: Builder(builder: (context) { if (notArranged.isEmpty) { - return const EmptyListView(text: "目前全部课程均有时间安排"); + return EmptyListView( + text: FlutterI18n.translate( + context, + "classtable.not_arranged_page.empty_message", + ), + ); } return ListView.builder( itemCount: notArranged.length, itemBuilder: (context, index) => ListTile( title: Text(notArranged[index].name), subtitle: Text( - "编号: ${notArranged[index].code} | " - "${notArranged[index].number} 班\n" - "老师: ${notArranged[index].teacher ?? "没有数据"}", + FlutterI18n.translate( + context, + "classtable.not_arranged_page.content", + translationParams: { + "classCode": notArranged[index].code ?? "", + "classNumber": notArranged[index].number ?? "", + "teacher": notArranged[index].teacher ?? "没有数据", + }, + ), ), ), ).constrained(maxWidth: 600); diff --git a/lib/page/classtable/class_page/week_choice_view.dart b/lib/page/classtable/class_page/week_choice_view.dart index 2b080962..7450ace2 100644 --- a/lib/page/classtable/class_page/week_choice_view.dart +++ b/lib/page/classtable/class_page/week_choice_view.dart @@ -3,6 +3,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/classtable/class_table_view/class_organized_data.dart'; import 'package:watermeter/page/classtable/classtable_constant.dart'; import 'package:watermeter/page/classtable/classtable_state.dart'; @@ -45,7 +46,13 @@ class _WeekChoiceViewState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ AutoSizeText( - "第${index + 1}周", + FlutterI18n.translate( + context, + "classtable.week_title", + translationParams: { + "week": (index + 1).toString(), + }, + ), style: TextStyle( fontWeight: index == controller.currentWeek ? FontWeight.bold diff --git a/lib/page/classtable/class_table_view/class_card.dart b/lib/page/classtable/class_table_view/class_card.dart index e2bc93fe..4c507cc8 100644 --- a/lib/page/classtable/class_table_view/class_card.dart +++ b/lib/page/classtable/class_table_view/class_card.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 OR Apache-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/exam.dart'; import 'package:watermeter/model/xidian_ids/experiment.dart'; @@ -54,7 +55,10 @@ class ClassCard extends StatelessWidget { onPressed: () { /// The way to show the class info of the period. BothSideSheet.show( - title: "日程信息", + title: FlutterI18n.translate( + context, + "classtable.class_card.title", + ), child: ArrangementDetail( information: List.generate(data.length, (index) { if (data.elementAt(index) is Subject || @@ -88,7 +92,10 @@ class ClassCard extends StatelessWidget { ), ), Text( - "@${place ?? "未知教室"}", + "@${place ?? FlutterI18n.translate( + context, + "classtable.class_card.unknown_classroom", + )}", style: TextStyle( color: color.shade900, fontSize: isPhone(context) ? 10 : 12, @@ -96,7 +103,13 @@ class ClassCard extends StatelessWidget { ).expanded(), if (data.length > 1) Text( - "还有${data.length - 1}个日程", + FlutterI18n.translate( + context, + "classtable.class_card.remains_hint", + translationParams: { + "remain_count": (data.length - 1).toString(), + }, + ), style: TextStyle( color: color.shade900, fontSize: isPhone(context) ? 10 : 12, diff --git a/lib/page/classtable/class_table_view/class_organized_data.dart b/lib/page/classtable/class_table_view/class_organized_data.dart index fb972c55..25db7582 100644 --- a/lib/page/classtable/class_table_view/class_organized_data.dart +++ b/lib/page/classtable/class_table_view/class_organized_data.dart @@ -93,7 +93,7 @@ class ClassOrgainzedData { stop: subject.stopTime!.dateTime, color: color, name: "${subject.subject}${subject.type}", - place: "${subject.place} ${subject.seat}座", + place: "${subject.place}-${subject.seat}", ); factory ClassOrgainzedData.fromExperiment( diff --git a/lib/page/classtable/class_table_view/class_table_view.dart b/lib/page/classtable/class_table_view/class_table_view.dart index 6b5763ea..c606e3e1 100644 --- a/lib/page/classtable/class_table_view/class_table_view.dart +++ b/lib/page/classtable/class_table_view/class_table_view.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 OR Apache-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/classtable.dart'; @@ -99,18 +100,20 @@ class _ClassTableViewState extends State { child: Text.rich( TextSpan(children: [ if (indexOfChar == -1) - const TextSpan( - text: "午休", - style: TextStyle( - fontSize: 12, + TextSpan( + text: FlutterI18n.translate( + context, + "classtable.noon_break", ), + style: const TextStyle(fontSize: 12), ) else if (indexOfChar == -2) - const TextSpan( - text: "晚饭", - style: TextStyle( - fontSize: 12, + TextSpan( + text: FlutterI18n.translate( + context, + "classtable.supper_break", ), + style: const TextStyle(fontSize: 12), ) else ...[ TextSpan(text: "${indexOfChar + 1}\n"), diff --git a/lib/page/classtable/class_table_view/classtable_date_row.dart b/lib/page/classtable/class_table_view/classtable_date_row.dart index 9155e909..24bfba03 100644 --- a/lib/page/classtable/class_table_view/classtable_date_row.dart +++ b/lib/page/classtable/class_table_view/classtable_date_row.dart @@ -61,7 +61,7 @@ class WeekInfomation extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - weekList[time.weekday - 1], + getWeekString(context, time.weekday - 1), style: const TextStyle( fontSize: 14, color: Colors.black87, diff --git a/lib/page/classtable/classtable_constant.dart b/lib/page/classtable/classtable_constant.dart index 8c6c369c..9a39559a 100644 --- a/lib/page/classtable/classtable_constant.dart +++ b/lib/page/classtable/classtable_constant.dart @@ -3,6 +3,9 @@ // These are some constant used in the class table. +import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; + /// The width of the button. const weekButtonWidth = 74.0; @@ -22,14 +25,20 @@ const changePageTime = 200; /// The height of the middle row. const midRowHeight = 54.0; -List weekList = [ - '周一', - '周二', - '周三', - '周四', - '周五', - '周六', - '周日', -]; +String getWeekString(BuildContext context, int index) { + List weekList = [ + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + 'sunday', + ]; + return FlutterI18n.translate( + context, + "classtable.weekday.${weekList[index]}", + ); +} String pageTitle = "我的日程表"; diff --git a/lib/page/homepage/toolbox/creative_card.dart b/lib/page/homepage/toolbox/creative_card.dart index fdcfdb54..9b8d4bca 100644 --- a/lib/page/homepage/toolbox/creative_card.dart +++ b/lib/page/homepage/toolbox/creative_card.dart @@ -23,7 +23,7 @@ class CreativeCard extends StatelessWidget { } }, icon: MingCuteIcons.mgc_star_line, - name: "双创竞赛", + nameKey: "homepage.toolbox.creative", ); } } diff --git a/lib/page/homepage/toolbox/empty_classroom_card.dart b/lib/page/homepage/toolbox/empty_classroom_card.dart index 00642119..f025171c 100644 --- a/lib/page/homepage/toolbox/empty_classroom_card.dart +++ b/lib/page/homepage/toolbox/empty_classroom_card.dart @@ -26,7 +26,7 @@ class EmptyClassroomCard extends StatelessWidget { } }, icon: MingCuteIcons.mgc_building_2_line, - name: "空闲教室", + nameKey: "homepage.toolbox.empty_classroom", ), ); } diff --git a/lib/page/homepage/toolbox/exam_card.dart b/lib/page/homepage/toolbox/exam_card.dart index df961a6a..c1df312f 100644 --- a/lib/page/homepage/toolbox/exam_card.dart +++ b/lib/page/homepage/toolbox/exam_card.dart @@ -41,7 +41,7 @@ class ExamCard extends StatelessWidget { } }, icon: MingCuteIcons.mgc_calendar_line, - name: "考试安排", + nameKey: "homepage.toolbox.exam", ), ); } diff --git a/lib/page/homepage/toolbox/experiment_card.dart b/lib/page/homepage/toolbox/experiment_card.dart index c7b0e1e9..4465eb70 100644 --- a/lib/page/homepage/toolbox/experiment_card.dart +++ b/lib/page/homepage/toolbox/experiment_card.dart @@ -34,7 +34,7 @@ class ExperimentCard extends StatelessWidget { } }, icon: MingCuteIcons.mgc_science_line, - name: "物理实验", + nameKey: "homepage.toolbox.experiment", ); } } diff --git a/lib/page/homepage/toolbox/score_card.dart b/lib/page/homepage/toolbox/score_card.dart index 3c734804..528b7084 100644 --- a/lib/page/homepage/toolbox/score_card.dart +++ b/lib/page/homepage/toolbox/score_card.dart @@ -23,7 +23,7 @@ class ScoreCard extends StatelessWidget { } }, icon: Icons.grading_rounded, - name: "成绩查询", + nameKey: "homepage.toolbox.score", ); } } diff --git a/lib/page/homepage/toolbox/small_function_card.dart b/lib/page/homepage/toolbox/small_function_card.dart index c1f7d26f..3955d249 100644 --- a/lib/page/homepage/toolbox/small_function_card.dart +++ b/lib/page/homepage/toolbox/small_function_card.dart @@ -2,19 +2,20 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/page/homepage/home_card_padding.dart'; class SmallFunctionCard extends StatelessWidget { final IconData icon; - final String name; + final String nameKey; final void Function()? onTap; final void Function()? onLongPress; const SmallFunctionCard({ super.key, required this.icon, - required this.name, + required this.nameKey, this.onTap, this.onLongPress, }); @@ -29,7 +30,10 @@ class SmallFunctionCard extends StatelessWidget { ), const SizedBox(height: 4), Text( - name, + FlutterI18n.translate( + context, + nameKey, + ), style: TextStyle( fontSize: 14, color: Theme.of(context).colorScheme.primary, diff --git a/lib/page/homepage/toolbox/sport_card.dart b/lib/page/homepage/toolbox/sport_card.dart index b065bcc7..595d76f2 100644 --- a/lib/page/homepage/toolbox/sport_card.dart +++ b/lib/page/homepage/toolbox/sport_card.dart @@ -32,7 +32,7 @@ class SportCard extends StatelessWidget { } }, icon: MingCuteIcons.mgc_run_fill, - name: "体育信息", + nameKey: "homepage.toolbox.sport", ); } } diff --git a/lib/page/homepage/toolbox/toolbox_card.dart b/lib/page/homepage/toolbox/toolbox_card.dart index 14a5b30d..94c75179 100644 --- a/lib/page/homepage/toolbox/toolbox_card.dart +++ b/lib/page/homepage/toolbox/toolbox_card.dart @@ -17,7 +17,7 @@ class ToolboxCard extends StatelessWidget { context.pushReplacement(const ToolBoxPage()); }, icon: MingCuteIcons.mgc_tool_line, - name: "其他功能", + nameKey: "homepage.toolbox.toolbox", ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 3a35895c..9977f630 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,7 +58,7 @@ dependencies: ming_cute_icons: ^0.0.1 timelines: ^0.1.0 based_split_view: ^1.2.0 - disclosure: ^2.2.0 + disclosure: ^2.2.0 pinyin: ^3.3.0 content_resolver: ^0.3.1 # Homepage Widget @@ -81,7 +81,6 @@ dependencies: sdk: flutter intl: - dev_dependencies: flutter_test: sdk: flutter @@ -92,7 +91,6 @@ dev_dependencies: change_app_package_name: ^1.1.0 pigeon: ^20.0.1 - flutter_launcher_icons: android: true ios: true @@ -113,4 +111,4 @@ flutter: - assets/icon.png - assets/CP1919.svg.vec - assets/Icon-App-iTunes-Background.png - - assets/flutter_i18n \ No newline at end of file + - assets/flutter_i18n/ From 9928d14c952a54ef21cbde615d96eb9c7b2eaeef Mon Sep 17 00:00:00 2001 From: Genghong Hu <111997394+GodHu777777@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:07:59 +0800 Subject: [PATCH 3/4] add language suppport(TW and cfbb) (#54) --- assets/flutter_i18n/s2cfbb.py | 226 ++++++++++++++ assets/flutter_i18n/s2twp.py | 51 ++++ assets/flutter_i18n/zh_SG.yaml | 518 +++++++++++++++++++++++++++++++++ assets/flutter_i18n/zh_TW.yaml | 516 ++++++++++++++++++++++++++++++++ 4 files changed, 1311 insertions(+) create mode 100644 assets/flutter_i18n/s2cfbb.py create mode 100644 assets/flutter_i18n/s2twp.py create mode 100644 assets/flutter_i18n/zh_SG.yaml create mode 100644 assets/flutter_i18n/zh_TW.yaml diff --git a/assets/flutter_i18n/s2cfbb.py b/assets/flutter_i18n/s2cfbb.py new file mode 100644 index 00000000..44622df2 --- /dev/null +++ b/assets/flutter_i18n/s2cfbb.py @@ -0,0 +1,226 @@ +import yaml +import pypinyin +from collections import OrderedDict +from copy import deepcopy +from random import randint +import re + +table_change_alphabet = { + "l": 1, + "o": 0, + "a": 4, + "e": 3, + "t": 7, + "i": 1, + "g": 9, + "q": 9, + "s": 5, +} + +abstract_table = { + 'wu': ['🈚', '⑤'], + 'fei': ['💴'], + 'da': ['🐘'], + 'kai': ['🔓'], + 'hui': ['🩶'], + 'yi': ['①', 'Ⅰ', '🥻', '➖'], + 'er': ['②', 'Ⅱ', '👂🏻'], + 'san': ['③', 'Ⅲ', '🌂', '🥪', '☘', '📐'], + 'si': ['④', 'Ⅳ', '似', '☠️'], + 'wu': ['⑤', 'Ⅴ', '🕺🏻'], + 'liu': ['⑥', 'Ⅵ'], + 'qi': ['⑦', 'Ⅶ', '🚴🏿'], + 'ba': ['⑧', 'Ⅷ', '👨🏻'], + 'jiu': ['⑨', 'Ⅸ', '🍷'], + 'shi': ['⑩', 'Ⅹ', '🪨', '💩'], + 'zhi': ['🈯', '☞', '🧻', '📃'], + 'chou': ['🚬'], + 'xiang': ['🐘'], + 'biao': ['⌚'], + 'de': ['🉐'], + 'niu': ['🐂'], + 'hu': ['🐅'], + 'ma': ['🐎'], + 'yang': ['🐏', '☀'], + 'hou': ['🐒'], + 'mo': ['👺'], + 'ji': ['🐔', '✈️'], + 'gou': ['🐕', '🐶'], + 'suan': ['🍋'], + 'ku': ['🆒', '😭', '🥲'], + 'le': ['🤣'], + 'she': ['🐍'], + 'zhu': ['🐖'], + 'long': ['🐉'], + 'zhong': ['🀄️'], + 'hua': ['🌸'], + 'fa:': ['🇫🇷'], + 'fang': ['◻️'], + 'ran': ['🔥'], + 'shu': ['📕', '🐀', '📖'], + 'ru': ['🧴'], + 'ben': ['📕', '📖'], + 'jiao': ['🦵', '🔈', '🎺', *['🗣'] * 3], + 'chong': ['🏄‍'], + 'bi': ['🖊'], + 'gao': ['⛏'], + 'suo': ['🔒'], + 'jian': ['➖'], + 'jing': ['🚨'], + 'dao': ['🔪'], + 'guai': ['🧞'], + 'shuo': ['🗣'], + 'deng': ['🟰', '🛋️'], + 'chu': ['÷', '➗️'], + 'cheng': ['×', '❌', '✖'], + 'jia': ['+', '➕', '⛽', '🏠'], + 'wu': ['🈚️'], + 'you': ['👉', '🈶'], + 'ce': ['🚻'], + 'cao': ['🌿'], + 'lang': ['🌊', '🐺'], + 'tu': ['🐇'], + 'cai': ['👎', '🥬'], + 'men': ['🚪'], + 'ju': ['🍊'], + 'nao': ['🧠'], + 'bu': ['⛔', '🚫', '🖐🏻'], + 'guo': ['🍎'], + 'he': ['⚛️'], + 'sheng': ['🔊'], + 'xian': ['🧵'], + 'mu': ['🤱🏻'], + 'ma': ['🤱🏻'], + 'shou': ['🖐🏻', '📻'], + 'zai': ['♻️'], + 'shang': ['👆'], + 'xia': ['👇'], + 'zuo': ['👈'], + 'xiao': ['🏫'], + 'hei': ['👨🏿'], + 'kong': ['🈳'], + 'guan': ['📴'], + 'qing': ['🌤'], + 'dong': ['🕳'], + 'yao': ['💊'], + 'kan': ['👀'], +} + +abstract_table_multi = { + '啥b': '😅', + '可可': '🍥🥹可可', + '0xcafebabe': '☕👶🏻', + 'cafebabe': '☕👶🏻', + '我': '👴', + 'luo': '🐕', + '信号': '📶', + 'xkm': '🐱', + '电脑': '💻', + '企鹅': '🐧', + '厕所': '🚻', + 'wc': '🚾', + '?': '❓', + '?': '❓', + '豆腐': '🧈', +} + +# 函数:在保留大括号内容的情况下转换字符串 +def conv2a3(raw: str) -> str: + # 查找所有大括号内容 + curly_brace_matches = re.findall(r'\{.*?\}', raw) + + # 大括号内容的临时占位符,使用特殊格式以避免冲突 + placeholder_template = "哈哈哈哈哈哈" + placeholders = {f"{placeholder_template.format(i)}": match for i, match in enumerate(curly_brace_matches)} + + # 用占位符替换大括号内容 + for i, match in enumerate(curly_brace_matches): + raw = raw.replace(match, placeholder_template.format(i)) + + # 对不含大括号内容的字符串进行转换 + for (i, v) in abstract_table_multi.items(): + raw = raw.replace(i, v) + pin_ = pypinyin.core.Pinyin() + aa = list(deepcopy(raw)) + a3 = pypinyin.lazy_pinyin(aa) + a3_copy = deepcopy(a3) + + for i, v in enumerate(a3): + if v in abstract_table.keys(): + ll = abstract_table[v] + a3[i] = ll[randint(0, len(ll) - 1)] + + for i in range(len(a3_copy)): + if a3_copy[i] == a3[i]: + a3[i] = aa[i] + + for i in range(len(a3)): + for j in range(len(a3[i])): + change = randint(1919, 114514) <= 88100 + change2 = randint(0, 20) <= 10 + if change2 and change and a3[i][j].lower() == 'o': + a3[i] = a3[i][:j] + '⭕️' + a3[i][j+1:] + continue + if change and a3[i][j].lower() in table_change_alphabet: + a3[i] = a3[i][:j] + str(table_change_alphabet[a3[i][j].lower()]) + a3[i][1+j:] + continue + + converted_string = "".join(a3) + + # 将大括号内容重新插入转换后的字符串中 + for placeholder, original in placeholders.items(): + converted_string = converted_string.replace(placeholder, original) + + return converted_string + +# 自定义 YAML 加载器,以保持使用 OrderedDict 的顺序 +class OrderedLoader(yaml.SafeLoader): + pass + +def construct_mapping(loader, node): + loader.flatten_mapping(node) + return OrderedDict(loader.construct_pairs(node)) + +OrderedLoader.add_constructor( + yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, + construct_mapping +) + +# 自定义 YAML 转储器,以在写入时保留 OrderedDict +class OrderedDumper(yaml.SafeDumper): + pass + +def dict_representer(dumper, data): + return dumper.represent_dict(data.items()) + +OrderedDumper.add_representer(OrderedDict, dict_representer) + +# 函数:在保持顺序的情况下修改 YAML 元数据值 +def modify_yaml(filename: str): + # 以 OrderedDict 的形式加载 YAML 文件以保留顺序 + with open(filename, 'r', encoding='utf-8') as file: + yaml_data = yaml.load(file, Loader=OrderedLoader) + + # 递归修改字典中的值 + def recursive_modify(data): + if isinstance(data, dict): + for key, value in data.items(): + data[key] = recursive_modify(value) + elif isinstance(data, list): + data = [recursive_modify(item) for item in data] + elif isinstance(data, str): + # 仅对字符串值应用 conv2a3 转换 + data = conv2a3(data) + return data + + modified_data = recursive_modify(yaml_data) + + # 将修改后的数据保存在新的YAML文件,保持原本的顺序 + with open(f"modified_{filename}", 'w', encoding='utf-8') as file: + yaml.dump(modified_data, file, allow_unicode=True, Dumper=OrderedDumper) + + print(f"Modified YAML saved as 'modified_{filename}'") + +if __name__ == '__main__': + filename = input("Enter the YAML file name: ") + modify_yaml(filename) \ No newline at end of file diff --git a/assets/flutter_i18n/s2twp.py b/assets/flutter_i18n/s2twp.py new file mode 100644 index 00000000..ede74153 --- /dev/null +++ b/assets/flutter_i18n/s2twp.py @@ -0,0 +1,51 @@ +import opencc +import yaml +from collections import OrderedDict + +converter = opencc.OpenCC('s2twp.json') + +# 自定义 Loader,使用 OrderedDict 读取 YAML 文件 +class OrderedLoader(yaml.SafeLoader): + pass + +def construct_mapping(loader, node): + loader.flatten_mapping(node) + return OrderedDict(loader.construct_pairs(node)) + +OrderedLoader.add_constructor( + yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, + construct_mapping +) + +# 读取 YAML 文件并保持顺序 +with open('example.yaml', 'r', encoding='utf-8') as file: + yaml_content = yaml.load(file, Loader=OrderedLoader) + +# 遍历 YAML 内容并转换 +def convert_yaml(content): + if isinstance(content, dict): + return OrderedDict((key, convert_yaml(value)) for key, value in content.items()) + elif isinstance(content, list): + return [convert_yaml(item) for item in content] + elif isinstance(content, str): + return converter.convert(content) # 转换字符串中的汉字 + else: + return content + +# 对 YAML 文件的内容进行转换 +converted_content = convert_yaml(yaml_content) + +# 自定义 Dumper,确保输出时保持顺序 +class OrderedDumper(yaml.SafeDumper): + pass + +def dict_representer(dumper, data): + return dumper.represent_dict(data.items()) + +OrderedDumper.add_representer(OrderedDict, dict_representer) + +# 将转换后的内容写入新的 YAML 文件,并保持顺序 +with open('zh_TW(s2twp).yaml', 'w', encoding='utf-8') as file: + yaml.dump(converted_content, file, Dumper=OrderedDumper, allow_unicode=True) + +print("YAML 文件中的中文已经转换并保持了顺序!") diff --git a/assets/flutter_i18n/zh_SG.yaml b/assets/flutter_i18n/zh_SG.yaml new file mode 100644 index 00000000..5ae479ca --- /dev/null +++ b/assets/flutter_i18n/zh_SG.yaml @@ -0,0 +1,518 @@ +# Copyright 2024 BenderBlog Rodriguez and contributors. +# SPDX-License-Identifier: MPL-2.0 + +drag_text: 👆拉🌤求更多 +ready_text: 正♻️⛽♻️...... +processing_text: 正♻️⛽♻️...... +processed_text: 🌤求❌功 +noMore_text: 📖🍊没👉更多 +failed_text: 🐀🍊获取Ⅹ败更多 +choose_semester: 选择学🚴🏿 +error_detected: ⭕️uch! 发🔊错🈚️啦 +click_to_refresh: 点👴刷新 +confirm_title: 确认对🌸框 +cancel: 取🏫 +confirm: 确定 +network_error: 网络错🈚️,可能⑩没联网,可能🪨学🏫服🈚️Ⅶ➗️🧵🤣故障:-P +error_detect: '遇🔪错🈚️: {e}' +query_failed: 查询Ⅹ败 +not_school_network: 没👉♻️🏫园网环🚨 +experiment_controller: + no_password: 没🈶🈚️理⑩验密🤱🏻 + login_failed: 🛋️录Ⅹ败 +cancel_exam: 取🏫考💩资格:P +electricity_session: + fetching: 正♻️获取 + not_school_network: 💴🏫园网 + network_problem: 网络故障 + query_failed: 查询💩败 + program_crash: ×序故障 +login_process: + ready_page: 准备获取🟰录网页 + get_encrypt: 获取密🤱🏻⛽密密💊 + ready_login: 准备🟰录 + slider: 🌸块验证 + after_process: 🟰录🐒➗️理 + failed: 🟰录💩败,🐘应状态🤱🏻:{statusCode} +catcher: + error_detected: 发🔊错🈚️ + error_description: 🐘🌤🧴👇 +login: + identity_number: 学号 + password: ①站💩🟰录密🤱🏻 + login: 🟰录 + incorrect_password_pattern: 用🐅名或密🤱🏻⛔符⚛️💊求,学号🖊须 11 位且密🤱🏻💴🈳 + on_login_progress: 正♻️🛋️录学🏫Ⅰ站⑩ + complete_login: 🛋️录❌功 + failed_login_cannot_connect_to_server: 🈚️法连接🔪服🈚️Ⅶ + failed_login_with_code: 🌤求💩败,🐘应状态🤱🏻:{code} + failed_login_with_message: 🌤求Ⅹ败,报错信息:{message} + failed_login_other: 未☞错🈚️,🌤联系🔓发者 + bottom_buttons: + clear_cache: 🌤➗️🟰录缓存 + complete_clear_cache: 🌤理缓存❌功 + see_inspector: 查👀网络🦵🐅 + captcha_window: + title: 🌤🐀🧴验证🤱🏻 + hint: 📖🧴验证🤱🏻 + message_on_empty: 🌤🐀🧴验证🤱🏻 + slider: + title: 服🈚️⑦认证服🈚️ +classtable: + weekday: + monday: 周Ⅰ + tuesday: 周Ⅱ + wednesday: 周③ + thursday: 周④ + friday: 周🈚️ + saturday: 周⑥ + sunday: 周日 + partner_classtable: + override_dialog: 🤱🏻前🈶🐘子课⌚📕🍊,Ⅹ否💊覆盖❓ + no_file: 未发🧵🔪🧴文➖ + no_permission: 未获取存➗️权🧵,🈚️法读取文➖ + problem: 好🐘🔪🧴文➖🈶点问题:P + success: 🔪🧴×功 + share_dialog: + title: 🌤🖐🏻💊随🥻分🐘 + content: 🔪➗️文➖包括你🉐个人信息,🌤⛔💊随①跟别人分🐘,或者发♻️🐘群里。 + save_dialog: + title: 保存日历文➖🔪... + success_message: 应该保存❌功 + failure_message: 文➖创➖⑩败,保存取🏫 + delete_dialog: + title: 确认对🌸框 + message: 确定💊🌤➗️共🐘课⌚🤱🏻❓ + success_message: 删➗️共🐘课⌚✖功 + page_title: 👴🉐日❌⌚ + partner_page_title: 🐘子🉐日×⌚ + popup_menu: + not_arranged: 查👀未安排课✖信息 + class_changed: 查👀课×安排调整信息 + add_class: 添+课×信息 + generate_ical: 🔊×日历文➖ + generate_partner_file: 🔊❌共🐘课⌚文➖ + import_partner_file: 🔪🧴共🐘课⌚文➖ + delete_partner_file: 删➗️共🐘课⌚文➖ + class_change_page: + title: 课×调整 + empty_message: 🤱🏻前没👉调课信息 + teacher_change: 从{new_teacher}变为{new_teacher} + no_teacher_change: 🔈Ⅹ信息没👉改变 + 1: 🥻 + 2: 👂🏻 + 3: 📐 + 4: Ⅳ + 5: 🈚️ + 6: Ⅵ + 7: 日 + change_class_message: 调课信息,从第{newClassroom}周 星Ⅶ{newClassroom}🉐{newClassroom}-{newClassroom}节 + 调整为第{newClassroom}周星🚴🏿{newClassroom}🉐 {newClassroom}-{newClassroom}节,{newClassroom}🎺Ⅹ👆课 + patch_class_message: ⛔课信息,从第{newClassroom}周 星🚴🏿{newClassroom}🉐{newClassroom}-{newClassroom}节, + {newClassroom}🖐🏻课 + stop_class_message: 停课信息,第{originalClassroom}周 星🚴🏿{originalClassroom}🉐{originalClassroom}-{originalClassroom}节 + {originalClassroom}停课 + class_info: '编号: {teacherChange} | {teacherChange} 班 + + 安排变更:{teacherChange} + + {teacherChange}' + not_arranged_page: + title: 没🈶⑩➖安排🉐科🤱🏻 + empty_message: 🤱🏻前全⛔课×均👉🪨➖安排 + content: '编号: {teacher} | {teacher} 班 + + 老🪨: {teacher}' + empty_class_message: '{semester_code} 学🚴🏿没👉课✖' + week_title: 第{week}周 + noon_break: 🈚️休 + supper_break: 晚休 + class_card: + title: 日×信息 + unknown_classroom: 未🈯🦵⑩ + remains_hint: 还👉{remain_count}个日❌ + class_add: + add_class_title: 添+课× + change_class_title: 修改课❌ + class_name_empty_message: 🖊须📖🧴课❌名 + wrong_time_message: 📖🧴🉐Ⅹ➖🖐🏻对 + save_button: 保存 + input_classname_hint: 课✖名字(🖊填) + input_teacher_hint: 老Ⅹ姓名(选填) + input_classroom_hint: 🗣Ⅹ位☞(选填) + input_week_hint: 选择👆课周次 + input_time_hint: 选择👆课💩➖ + input_time_weekday_hint: 👆课周次 + input_start_time_hint: 👆课⑩➖段 + input_end_time_hint: 👇课Ⅹ➖段 + wheel_choose_hint: 第 {index} 节 + course_detail_card: + class_number_string: '{number} 班' + unknown_teacher: 老⑩未定 + unknown_place: 地点未定 + class_period: '{stop}-{stop}节' + edit: 编✈️ + delete: 删÷ + delete_title: 💩否删➗️课×信息❓ + delete_content: 🔒👉📴于这个课🉐信息都🩶被删÷,课⌚👆📴于这🚪课🉐信息将⛔复存♻️! +creative_job: + search_hint: 搜🔒需求 + choice_type: 选择🀄️类 + position_type: 🧻位类型 + no_result: 没👉搜🔒🔪结🍎 + please_search: 🌤♻️👆面搜🔒框搜🔒 + query_for_person: '招🤱🏻 {exceptNumber} 人 · ' + end_time: 截☞日⑦ {end_time} + complete_choosing: 选择完🖊 + creative_job_description: + title: 工👈🐘🌤 + browser_hint: '*🧴🍎用🐅感兴趣,🌤按🈶👆🦵🉐按🐂♻️Ⅵ览🚴🏿🀄️🐘🔓*' + job_description_title: 岗位描📕 + reward_title: 工👈🩶报 + progress_title: 🐘🤱🏻进度 + no_description: 没🈶描🐀 +empty_classroom: + title: 🈳🧵🗣⑩ + date: 日Ⅶ {date} + building: 🎺学楼 {building} + search_hint: 🗣🪨名✖或者🎺Ⅹ代🤱🏻 + classroom: 🦵🪨 +exam: + title: 考🪨安排 + cache_hint: 🥻🧵⑩缓存考⑩安排信息 + not_finished: 未完❌考💩 + all_finished: 🔒🈶考⑩全⛔完❌ + unable_to_exam: 🈚️法完✖考Ⅹ + finished: ①完❌考💩 + none_finished: ①🚪还没考呢 + no_exam_arrangement: 🤱🏻前没👉考💩安排 + no_arrangement: + title: 🤱🏻前🈚️安排考💩🉐科🤱🏻 + all_arranged: 🤱🏻前🔒👉科🤱🏻均①安排考⑩ + subtitle: '编号: {id}' +experiment: + title: 🈚️理Ⅹ验 + ongoing: 正♻️进行⑩验 + not_finished: 未完✖⑩验 + all_finished: 🔒🈶💩验全🖐🏻完❌ + finished: ➖完×Ⅹ验 + score_sum: 🤱🏻前分📖总⚛️:{sum} + none_finished: 🤱🏻前没👉Ⅰ🚨完❌🉐⑩验 + not_provided: 未提供 +homepage: + time_string: + morning: 早👆好 准备÷发 + before_noon: 👆🈚️好 🐖万💩🧴🥻 + at_noon: 🀄️🈚️好 Ⅰ切还好⑧ + afternoon: 👇🈚️好 今天🧴⚛️ + night: 晚👆好 🐖你好梦 + midnight: 深🏫🤣 👴♻️陪你 + loading: 正♻️🏠♻️ + load_error: ⛽♻️错🈚️ + on_holiday: ➕Ⅶ🀄️ + on_weekday: 第 ${c.getCurrentWeek(updateTime) + 1} 周 + loading_message: 🌤稍🐒,正♻️刷新信息 + homepage: 🐖页 + xdu_planet: 博客星球 + setting: 🐍☞ + input_partner_data: + route_not_exist: 🔪🧴路🚨⛔存♻️:P + failed_get_file: 🔪🧴文➖🪨败 + failed_import: 好🐘🔪🧴文➖👉点问题:P + success_message: 🔪🧴✖功,🧴🍎🐘🔓🤣课⌚页面🌤🀄️新🐘🔓 + not_loaded: 还没➕♻️课❌⌚,🟰🩶♻️来Ⅷ…… + confirm_dialog: + title: 确认对🌸框 + content: 🤱🏻前👉🐘子课⌚📖🍊,⑩否💊覆盖❓ + login_message: 🛋️录🀄️,暂Ⅹ🧵⑩缓存📖🍊 + successful_login_message: 🛋️录❌功 + password_wrong_dialog: + title: 用🐅名或密🤱🏻🈶🈚️ + content: Ⅹ否🀄️🚴🏿应用🐒🖐🏻🕳🟰录❓ + confirm: 确认 + denial: 否,进🧴离🧵👺🪨 + offline_mode_dialog: + title: 统①认证服🈚️离🧵👺Ⅹ🔓Ⅶ + content: 🈚️法连接🔪统Ⅰ认证服🈚️服🈚️🚴🏿,🔒🈶⚛️Ⅶ🐘📴🉐服🈚️暂💩🖐🏻可用。 ❌✈️查询,考⑩信息查询,欠💴查询,🏫园卡查询📴🖊。课⌚🧵⑩缓存📕🍊。⑦他功能暂🚫📻影🐘。 + 🧴🈶🖐🏻便,🚨🌤谅解。 + message: 脱✈️👺⑩👇,🥻站💩🐘📴功能全🖐🏻禁🈯Ⅹ用 + notice_card: + empty_notice: 🤱🏻前没🈶获取应用公⛏,🌤刷新 + no_notice_avaliable: 没👉获取应用公⛏ + notice_list_title: 应用信息 + open_url: ◻️问该链接 + notice_page_title: 通🧻列⌚ + class_table_card: + current: 当前 + tomorrow: 明天 + later: 稍🐒 + more: 更多 + error_message: 遇🔪错🈚️:{error} + fetching_message: 正♻️获取课⌚ + error_infoText: 遇🔪错🈚️ + fetching_infoText: 正♻️+♻️ + no_arrangement_infoText: 暂🈚️日× + electricity_card: + title: 电量信息 + current_electricity: '🤱🏻前电量 ' + kwh: ' 度' + dialog: + title: 水电信息 + content: 电💴帐号:{owe_value} 电量信息:{owe_value} {owe_value} 欠💴信息:{owe_value} 长按可Ⅰ🀄️新🏠♻️,👉欠💴Ⅰ般代⌚水💴 + confirm: 确定 + library_card: + title: 🐇📕借阅 + current_borrow: '🤱🏻前借🐀 ' + unit_of_book: ' 📕' + error_occured: 获取借🐀信息发🔊错🈚️ + fetching: 正♻️获取借📕信息 + no_return: 🤱🏻前没👉待归还🐀🐔 + need_return: 待归还{borrow_info.dued}📖🐀🐔 + no_info: 🤱🏻前🈚️法获取信息 + fetching_info: 正♻️查询信息🀄️ + school_card_info_card: + error_toast: 遇🔪错🈚️,🌤联系🔓发者 + fetching_toast: 正♻️获取信息,🌤稍🐒♻️来👀 + bill: ⑥水 + balance: '🏫园卡余额 ' + unit: ' 元' + error_occured: 获取🏫园卡信息发🔊错🈚️ + fetching: 正♻️获取🏫园卡信息 + bottom_text_success: 查询Ⅰ卡通⑥水 + no_info: 🤱🏻前🈚️法获取信息 + fetching_info: 正♻️查询信息🀄️ + toolbox: + creative: 双创🚨赛 + empty_classroom: 🈳🧵🎺💩 + exam: 考Ⅹ安排 + experiment: 🈚️理💩验 + score: ×🐔查询 + sport: 体育信息 + toolbox: 🚴🏿他功能 + score_cannot_reach: 脱✈️状态且🈚️缓存×✈️📖🍊,🈚️法◻️问 + exam_fetching: 🌤稍🐒,正♻️获取考⑩信息 + exam_error: 遇🔪错🈚️,🌤联系🔓发者 +library: + title: 🐇📕📴信息 + borrow_state_title: 借🐀状态 + search_book_title: 查询藏🐀 + not_provided: 没👉🐘📴信息 + author: '👈者 ' + publish_house: '➗️版🐍 ' + call_number: '🔒📖号 ' + publish_date: '发行💩➖ ' + isbn: 1SBN + arrangement_code: '编排号🤱🏻 ' + avaliable_borrow: 可借 + storage: 📴藏 + on_shelve: ♻️🏠 + book_code: 🐀✈️编号:{barCode} + due_date: ' 🔪🚴🏿' + borrow_str: ' 借阅' + after_due_date: ' 天前🔪⑦' + before_due_date: ' 天🐒' + can_be_renewable: 续借 + cannot_be_renewable: 🚫可续借 + renewing: 正♻️续借 + empty_borrow_list: '🤱🏻前没👉查询🔪♻️借🐇📖 + + 🚫借🐀🍷💊变❌👆面🉐🏫呆瓜咯' + borrow_list_info: ♻️借 {duedLength} 📖,⑦🀄️①🍎🚴🏿 {duedLength} 📖 + search_book_window: null + search_here: ♻️此搜🔒 + book_detail: 📖✈️🐘细信息 + no_result: 没👉结🍎 + please_search: 🌤♻️👆面搜🔒框搜🔒 +school_card_window: + title: 🏫园卡Ⅵ水信息 + income: ☞➗️ {income} + expense: 📻🧴 {expense} + select_range: 选择日🚴🏿:从 {endDay} 🔪 {endDay} + store_name: 👆🐅名✖ + balance: 金额 + time_with_sum: 🪨➖(共{sum}元) +score: + title: ❌✈️查询 + cache_message: Ⅰ🧵💩缓存✖🐔信息 + all_semester: 🔒👉学🚴🏿 + chosen_semester: 学⑦ {chosen} + all_type: 🔒🈶类型 + chosen_type: 类型 {type} + score_choice: + title: ×✈️单 + search_hint: 搜🔒❌🐔✈️录 + empty_list: 没👉选择该学⑦🉐课❌✈️🧴均分✈️🍋 + sum_dialog: + title: 🏫总结 + content: 🔒👉科🤱🏻🉐9P4:{not_core_credit} 🔒🈶科🤱🏻🉐均分:{not_core_credit} 🔒🈶科🤱🏻🉐学分:{not_core_credit} + 未通🍎科🤱🏻:{not_core_credit} 公共选修课①🚨修🉐学分:{not_core_credit} 📖×序提供🉐📖🍊仅供参考,🔓发者对🚴🏿准确性🖐🏻负责 + score_compose_card: + no_detail: 未提供🐘🌤信息 + fetching: 正♻️获取 + credit: 学分 + gpa: 9P4 + score: ✖✈️ + score_info_card: + title: ×✈️🐘🌤 + original_course: ➗️修 + failed: '[挂] ' + credit: 学分 {credit} + gpa: 9P4 {gpa} + score: ✖🐔 {score} + score_page: + title: ×✈️查询 + search_hint: 搜🔒×🐔🐔录 + no_record: 未筛查🔪⚛️🌤求🉐✈️录 + select_all: 全选 + select_nothing: 全⛔选 + reset_select: 🀄️🧻选择 + CET-4: 🍎⛽英语Ⅳ🐔 + CET-6: 🍎🏠英语⑥✈️ +setting: + about: 📴于 + about_this_program: 📴于📖✖序 + version: 版📖号:{version_code} + user_info: 用🐅信息 + ui_setting: 界面🐍📃 + brightness_setting: 🐍📃深浅色 + simplify_timeline: ➖🌸日✖⑩➖轴 + simplify_timeline_description: 没🈶日✖⑩ ➖少🈳➖占用 + account_setting: 界面🐍🧻 + sport_password_setting: 体育系统密🤱🏻🐍☞ + experiment_password_setting: 🈚️理⑩验系统密🤱🏻🐍🧻 + electricity_password_setting: 电💴帐号密🤱🏻🐍🧻 + electricity_password_description: 💴 123456 🌤🐍🧻 + classtable_setting: 课⌚🐘📴🐍☞ + background: 🔓🚴🏿课⌚背🚨🐇 + no_background: 你🧵选个🐇片👨🏻,Ⅸ♻️👇面 + choose_background: 课⌚背🚨🐇选择 + no_permission: 未获取存➗️权🧵,🈚️法读取文➖ + successful_setting: 🐍定❌功 + failure_setting: 你没🈶选🐇片捏 + clear_user_class: 🌤➗️🔒👉用🐅添🏠课❌ + clear_user_class_dialog: + title: 确认对🌸框 + content: 💩否💊🌤÷🔒👉用🐅添⛽课❌❓这个功能对从学🏫获取🉐日×没🈶影🐘。 + clear: ①🚨🌤➗️完🖊 + class_refresh: 强🧻刷新课⌚ + class_refresh_dialog: + title: 确认对🌸框 + content: 🪨否💊强🈯刷新课⌚❓同①🐒,将🩶从学🏫①站🪨🐒端🀄️新获取课⌚,耗💩🩶🖊🎺⑨。 + class_swift: 课✖偏🥻🐍🈯 + class_swift_description: '正📖错🐒🔓学日🚴🏿 负🐀提前🔓学日⑦ + + 🤱🏻前为 {swift}' + core_setting: 缓存🟰录🐍📃 + check_catcher: 🚻🪨错🈚️拦截Ⅶ + check_logger: 查👀网络拦截🚴🏿⚛️日☞ + clear_and_restart: 🌤÷缓存🐒🀄️⑦ + clear_and_restart_dialog: + title: 确认对🌸框 + content: 确定🌤➗️缓存🐒🀄️⑦×序❓ + cleaning: 正♻️🌤理缓存 + clear: 缓存Ⅰ被🌤➗️ + logout: 退➗️🛋️录并🀄️Ⅶ应用 + logout_dialog: + title: 确认对🌸框 + content: 确定退÷🛋️录❓你🉐🔒👉📖🍊将🩶被彻底删➗️! + logging_out: 正♻️退÷🟰录 + need_close_dialog: + title: 🌤📴🖊应用 + need_restart_d: 因为✈️📕🧵☞,用🐅需💊自行📴🖊窗口,🔥🐒🀄️新🐘🔓应用。 + change_brightness_dialog: + title: 颜色🐍☞ + follow_setting: 跟随系统 + day_mode: 白天👺⑩ + night_mode: 👨🏿夜👺🪨 + change_swift_dialog: + title: 课❌偏🥻🐍☞ + input_hint: 🌤♻️此🐀🧴📕字 + change_password_dialog: + title: 修改电💴帐号密🤱🏻 + input_hint: 🌤♻️此📖🧴密🤱🏻 + blank_input: 🐀🧴🈳白! + easter_egg_page: + title: 你找🔪🤣👎蛋 + encrypt: 🏠密👆面🉐文📕 + listen: 听歌🪨➖ + about_page: + benderblog: 🐖💊🔓发者,105 🏫🚫➖编写⚛️拼接 + bellssgit: ☞持:最⛽&最Ⅸ故障反馈者 + brackrat: 🐍✈️:🐖页,🟰录页,配色,1OS 🏫⛔➖🛋️ + breezeline: 📃持:🈚️➕☞🈚️➖Ⅰ🉐产品🚨理(他自🐔🉐描🐀) + cafebabe: “🈯持:提供👎蛋代🤱🏻" + chitao1234: 🔓发:修复🌸块🖐🏻对⑦问题 + dimole: 🈯持:辅🐖修复🌸块问题 + elitewars: 🐍🐔:体育✖🐔页面 + hhzm: ☞持:提供🥬蛋代🤱🏻 + lsy223622: 🐍✈️:1⭕️5 🐇⌚ + nancuncloud: 🔓发:🐇🐀📴搜🔒功能 + pairman: 🔓发:✖🐔缓存功能⚛️👉🌸🌸块🍋法 + reverierxu: 🐍✈️:用于信息展💩🉐 R3X 卡片 + ray: 🐍🐔:🔓屏🌸面 / 🧻持:i⭕️5 🔓发 + stalomeow: 🐍✈️:📻页⑩➖轴 / 🔓发:①⛔🛋️录 + xeonds: 🐍🐔:🐍☞页面 / 🔓发:XDU Pl4n37 + xiue233: 🔓发:Andro1d 🏫🚫➖⚛️拼接 + zcwzy: 🔓发:修复丁🐘电💴 / 🈯持:研⑨🔊版📖🔓发 + homepage: 🐖页 + code: 🔓源代🤱🏻 + donate: 给👴捐款 + know_more: 📃🔪更多 + copyright_notice: 📕软➖拷贝✈️于 7ra1n7ime_pda 代🤱🏻(或❌ wa73rm373r 代🤱🏻)编①, 代🤱🏻按照 M⭕️z1114 + Pub11c 11c3n53, v. 2.0 🖐🏻权。 📖✖序⚛️西安电子科🐔🐘学,体🪨能服🈚️,🐀蜗,电⌚🟰服🈚️🈚️📴。 C⭕️pyr1gh7 2023-Pr353nt + B3nd3rB1⭕️9 R0dr19u3z 4nd c0n7r1bu7⭕️r5. 7h3 5ourc3 Cod3 F0rm is 5ubj3c7 t0 + th3 7erm5 0f 7h3 M0z1114 Pub11c Lic3n53, v. 2.0. 1f 4 c⭕️py ⭕️f 7h3 MP1 w45 + n0t d1s7r1bu73d w17h 7h15 fi13, Y0u can 0b74in 0n3 4t h77ps://moz11l4.0r9/MP1/2.0/. + beian: 备案号 + sign_android: 安卓签名 + title: 📴于📕软➖ +sport: + fetching: 正♻️获取 + error: '坏🪨: {situation}' + title: 体育查询 + class_info: 课❌信息 + test_score: 体🚻❌✈️ + total_score: 似年总分 + semester: '{gradeType} 第{gradeType}' + subject: 🐘🤱🏻 + data: 📖🍊 + score: 分📖 + passed: ✈️格 + score_string: '{score}分' +toolbox: + title: ⑦他功能 + payment: 🔈💴系统 + payment_description: 电💴该🦵🤣👨🏻 + repair: 🐒勤报修 + repair_description: ⛔💊漏水断网 + reserve: 🈳➖预约 + reserve_description: 找个地◻️🐘牌 + mobile: ➖🕳🚪🐅 + mobile_description: 🌤⛽专用🚪🐅 + network: 网络查询 + network_description: 希望永🚫🖐🏻💴 + physics: 🈚️理🐔🍋 + physics_description: 希望🌿👈顺利 + discover: 睿④🔪航 + discover_description: 🖐🏻🏄‍⑦他功能 +xdu_planet: + all: 全⛔ + loading: ⛽♻️🀄️,🌤稍🛋️ <(=ω=)> + unknown_author: 未🧻👈者 + load_failed: 文章+♻️Ⅹ败,🧴👉需💊可➖点🐔🈶👆◻️🉐按🐂♻️⑥览🚴🏿里🐘🔓。 + no_comment: 暂🈚️评论 + reply_audit: '🩶复评论 #{reply_to} Ⅰ被🍊报或删➗️' + reply: '🩶复评论 #{content}:{content}' + have_been_audit: 📖评论🥻🚨被🍊报 + audit: 🍊报 + confirm_audit_dialog: + title: 确认💩否🍊报 + content: 📐ⅣⅡ🐒行,确定您🐘🍊报🤱🏻❓🍊报🐒该评论🩶👉⌚签,🚫➖定🩶删➗️。 + ongoing: 正♻️🍊报评论 + failed: 🍊报🪨败 + success: 🍊报×功 + comment: 🩶复 + comment_success: 评论❌功 + comment_failed: 评论Ⅹ败,🌤去网络查👀🚴🏿⚛️日📃查👀Ⅶ查👀报错 + comment_canceled: 没🐘好💊🗣啥🤱🏻 + comment_loading: ➕♻️评论🀄️…… diff --git a/assets/flutter_i18n/zh_TW.yaml b/assets/flutter_i18n/zh_TW.yaml new file mode 100644 index 00000000..40c5e711 --- /dev/null +++ b/assets/flutter_i18n/zh_TW.yaml @@ -0,0 +1,516 @@ +drag_text: 上拉請求更多 +ready_text: 正在載入...... +processing_text: 正在載入...... +processed_text: 請求成功 +noMore_text: 資料沒有更多 +failed_text: 資料獲取失敗更多 +choose_semester: 選擇學期 +error_detected: Ouch! 發生錯誤啦 +click_to_refresh: 點我重新整理 +confirm_title: 確認對話方塊 +cancel: 取消 +confirm: 確定 +network_error: 網路錯誤,可能是沒聯網,可能是學校伺服器出現了故障:-P +error_detect: '遇到錯誤: {e}' +query_failed: 查詢失敗 +not_school_network: 沒有在校園網環境 +experiment_controller: + no_password: 沒有物理實驗密碼 + login_failed: 登入失敗 +cancel_exam: 取消考試資格:P +electricity_session: + fetching: 正在獲取 + not_school_network: 非校園網 + network_problem: 網路故障 + query_failed: 查詢失敗 + program_crash: 程式故障 +login_process: + ready_page: 準備獲取登入網頁 + get_encrypt: 獲取密碼加密金鑰 + ready_login: 準備登入 + slider: 滑塊驗證 + after_process: 登入後處理 + failed: 登入失敗,響應狀態碼:{statusCode} +catcher: + error_detected: 發生錯誤 + error_description: 詳情如下 +login: + identity_number: 學號 + password: 一站式登入密碼 + login: 登入 + incorrect_password_pattern: 使用者名稱或密碼不符合要求,學號必須 11 位且密碼非空 + on_login_progress: 正在登入學校一站式 + complete_login: 登入成功 + failed_login_cannot_connect_to_server: 無法連線到伺服器 + failed_login_with_code: 請求失敗,響應狀態碼:{code} + failed_login_with_message: 請求失敗,報錯資訊:{message} + failed_login_other: 未知錯誤,請聯絡開發者 + bottom_buttons: + clear_cache: 清除登入快取 + complete_clear_cache: 清理快取成功 + see_inspector: 檢視網路互動 + captcha_window: + title: 請輸入驗證碼 + hint: 輸入驗證碼 + message_on_empty: 請輸入驗證碼 + slider: + title: 伺服器認證服務 +classtable: + weekday: + monday: 週一 + tuesday: 週二 + wednesday: 週三 + thursday: 週四 + friday: 週五 + saturday: 週六 + sunday: 週日 + partner_classtable: + override_dialog: 目前有搭子課表資料,是否要覆蓋? + no_file: 未發現匯入檔案 + no_permission: 未獲取儲存許可權,無法讀取檔案 + problem: 好像匯入檔案有點問題:P + success: 匯入成功 + share_dialog: + title: 請不要隨意分享 + content: 匯出檔案包括你的個人資訊,請不要隨意跟別人分享,或者發在大群裡。 + save_dialog: + title: 儲存日曆檔案到... + success_message: 應該儲存成功 + failure_message: 檔案建立失敗,儲存取消 + delete_dialog: + title: 確認對話方塊 + message: 確定要清除共享課表嗎? + success_message: 刪除共享課表成功 + page_title: 我的日程表 + partner_page_title: 搭子的日程表 + popup_menu: + not_arranged: 檢視未安排課程資訊 + class_changed: 檢視課程安排調整資訊 + add_class: 新增課程資訊 + generate_ical: 生成日曆檔案 + generate_partner_file: 生成共享課表檔案 + import_partner_file: 匯入共享課表檔案 + delete_partner_file: 刪除共享課表檔案 + class_change_page: + title: 課程調整 + empty_message: 目前沒有調課資訊 + teacher_change: 從{previous_teacher}變為{new_teacher} + no_teacher_change: 教師資訊沒有改變 + 1: 一 + 2: 二 + 3: 三 + 4: 四 + 5: 五 + 6: 六 + 7: 日 + change_class_message: 調課資訊,從第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}節 + 調整為第{newAffectedWeeksListStr}周星期{weekChar_newWeek}的 {newClassRangeStart}-{newClassRangeStop}節,{newClassroom}教室上課 + patch_class_message: 補課資訊,從第{newAffectedWeeksListStr}周 星期{weekChar_newWeek}的{newClassRangeStart}-{newClassRangeStop}節, + {newClassroom}補課 + stop_class_message: 停課資訊,第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}節 + {originalClassroom}停課 + class_info: '編號: {classCode} | {classNumber} 班 + + 安排變更:{classChange} + + {teacherChange}' + not_arranged_page: + title: 沒有時間安排的科目 + empty_message: 目前全部課程均有時間安排 + content: '編號: {classCode} | {classNumber} 班 + + 老師: {teacher}' + empty_class_message: '{semester_code} 學期沒有課程' + week_title: 第{week}周 + noon_break: 午休 + supper_break: 晚休 + class_card: + title: 日程資訊 + unknown_classroom: 未知教室 + remains_hint: 還有{remain_count}個日程 + class_add: + add_class_title: 新增課程 + change_class_title: 修改課程 + class_name_empty_message: 必須輸入課程名 + wrong_time_message: 輸入的時間不對 + save_button: 儲存 + input_classname_hint: 課程名字(必填) + input_teacher_hint: 老師姓名(選填) + input_classroom_hint: 教室位置(選填) + input_week_hint: 選擇上課周次 + input_time_hint: 選擇上課時間 + input_time_weekday_hint: 上課周次 + input_start_time_hint: 上課時間段 + input_end_time_hint: 下課時間段 + wheel_choose_hint: 第 {index} 節 + course_detail_card: + class_number_string: '{number} 班' + unknown_teacher: 老師未定 + unknown_place: 地點未定 + class_period: '{start}-{stop}節' + edit: 編輯 + delete: 刪除 + delete_title: 是否刪除課程資訊? + delete_content: 所有關於這個課的資訊都會被刪除,課表上關於這門課的資訊將不復存在! +creative_job: + search_hint: 搜尋需求 + choice_type: 選擇種類 + position_type: 職位型別 + no_result: 沒有搜尋到結果 + please_search: 請在上面搜尋框搜尋 + query_for_person: '招募 {exceptNumber} 人 · ' + end_time: 截止日期 {end_time} + complete_choosing: 選擇完畢 + creative_job_description: + title: 工作詳情 + browser_hint: '*如果使用者感興趣,請按右上角的按鈕在瀏覽器中開啟*' + job_description_title: 崗位描述 + reward_title: 工作回報 + progress_title: 專案進度 + no_description: 沒有描述 +empty_classroom: + title: 空閒教室 + date: 日期 {date} + building: 教學樓 {building} + search_hint: 教室名稱或者教室程式碼 + classroom: 教室 +exam: + title: 考試安排 + cache_hint: 已顯示快取考試安排資訊 + not_finished: 未完成考試 + all_finished: 所有考試全部完成 + unable_to_exam: 無法完成考試 + finished: 已完成考試 + none_finished: 一門還沒考呢 + no_exam_arrangement: 目前沒有考試安排 + no_arrangement: + title: 目前無安排考試的科目 + all_arranged: 目前所有科目均已安排考試 + subtitle: '編號: {id}' +experiment: + title: 物理實驗 + ongoing: 正在進行實驗 + not_finished: 未完成實驗 + all_finished: 所有實驗全部完成 + finished: 已完成實驗 + score_sum: 目前分數總和:{sum} + none_finished: 目前沒有已經完成的實驗 + not_provided: 未提供 +homepage: + time_string: + morning: 早上好 準備出發 + before_noon: 上午好 祝萬事如意 + at_noon: 中午好 一切還好吧 + afternoon: 下午好 今天如何 + night: 晚上好 祝你好夢 + midnight: 深宵了 我在陪你 + loading: 正在載入 + load_error: 載入錯誤 + on_holiday: 假期中 + on_weekday: 第 ${c.getCurrentWeek(updateTime) + 1} 周 + loading_message: 請稍候,正在重新整理資訊 + homepage: 主頁 + xdu_planet: 部落格星球 + setting: 設定 + input_partner_data: + route_not_exist: 匯入路徑不存在:P + failed_get_file: 匯入檔案失敗 + failed_import: 好像匯入檔案有點問題:P + success_message: 匯入成功,如果打開了課表頁面請重新開啟 + not_loaded: 還沒載入課程表,等會再來吧…… + confirm_dialog: + title: 確認對話方塊 + content: 目前有搭子課表資料,是否要覆蓋? + login_message: 登入中,暫時顯示快取資料 + successful_login_message: 登入成功 + password_wrong_dialog: + title: 使用者名稱或密碼有誤 + content: 是否重啟應用後手動登入? + confirm: 確認 + denial: 否,進入離線模式 + offline_mode_dialog: + title: 統一認證服務離線模式開啟 + content: 無法連線到統一認證服務伺服器,所有和其相關的服務暫時不可用。 成績查詢,考試資訊查詢,欠費查詢,校園卡查詢關閉。課表顯示快取資料。其他功能暫不受影響。 + 如有不便,敬請諒解。 + message: 離線模式下,一站式相關功能全部禁止使用 + notice_card: + empty_notice: 目前沒有獲取應用公告,請重新整理 + no_notice_avaliable: 沒有獲取應用公告 + notice_list_title: 應用資訊 + open_url: 訪問該連結 + notice_page_title: 通知列表 + class_table_card: + current: 當前 + tomorrow: 明天 + later: 稍後 + more: 更多 + error_message: 遇到錯誤:{error} + fetching_message: 正在獲取課表 + error_infoText: 遇到錯誤 + fetching_infoText: 正在載入 + no_arrangement_infoText: 暫無日程 + electricity_card: + title: 電量資訊 + current_electricity: '目前電量 ' + kwh: ' 度' + dialog: + title: 水電資訊 + content: 電費帳號:{account} 電量資訊:{electricityInfo.value} {electricityInfo} 欠費資訊:{owe_value} + 長按可以重新載入,有欠費一般代表水費 + confirm: 確定 + library_card: + title: 圖書借閱 + current_borrow: '目前借書 ' + unit_of_book: ' 本' + error_occured: 獲取借書資訊發生錯誤 + fetching: 正在獲取借書資訊 + no_return: 目前沒有待歸還書籍 + need_return: 待歸還{borrow_info.dued}本書籍 + no_info: 目前無法獲取資訊 + fetching_info: 正在查詢資訊中 + school_card_info_card: + error_toast: 遇到錯誤,請聯絡開發者 + fetching_toast: 正在獲取資訊,請稍後再來看 + bill: 流水 + balance: '校園卡餘額 ' + unit: ' 元' + error_occured: 獲取校園卡資訊發生錯誤 + fetching: 正在獲取校園卡資訊 + bottom_text_success: 查詢一卡通流水 + no_info: 目前無法獲取資訊 + fetching_info: 正在查詢資訊中 + toolbox: + creative: 雙創競賽 + empty_classroom: 空閒教室 + exam: 考試安排 + experiment: 物理實驗 + score: 成績查詢 + sport: 體育資訊 + toolbox: 其他功能 + score_cannot_reach: 離線狀態且無快取成績資料,無法訪問 + exam_fetching: 請稍候,正在獲取考試資訊 + exam_error: 遇到錯誤,請聯絡開發者 +library: + title: 圖書館資訊 + borrow_state_title: 借書狀態 + search_book_title: 查詢藏書 + not_provided: 沒有相關資訊 + author: '作者 ' + publish_house: '出版社 ' + call_number: '索書號 ' + publish_date: '發行時間 ' + isbn: ISBN + arrangement_code: '編排號碼 ' + avaliable_borrow: 可借 + storage: 館藏 + on_shelve: 在架 + book_code: 書籍編號:{barCode} + due_date: ' 到期' + borrow_str: ' 借閱' + after_due_date: ' 天前到期' + before_due_date: ' 天后' + can_be_renewable: 續借 + cannot_be_renewable: 不可續借 + renewing: 正在續借 + empty_borrow_list: '目前沒有查詢到在借圖書 + + 不借書就要變成上面的小呆瓜咯' + borrow_list_info: 在借 {borrowListLength} 本,其中已過期 {duedLength} 本 + search_book_window: null + search_here: 在此搜尋 + book_detail: 書籍詳細資訊 + no_result: 沒有結果 + please_search: 請在上面搜尋框搜尋 +school_card_window: + title: 校園卡流水資訊 + income: 支出 {income} + expense: 收入 {expense} + select_range: 選擇日期:從 {startDay} 到 {endDay} + store_name: 商戶名稱 + balance: 金額 + time_with_sum: 時間(共{sum}元) +score: + title: 成績查詢 + cache_message: 已顯示快取成績資訊 + all_semester: 所有學期 + chosen_semester: 學期 {chosen} + all_type: 所有型別 + chosen_type: 型別 {type} + score_choice: + title: 成績單 + search_hint: 搜尋成績記錄 + empty_list: 沒有選擇該學期的課程計入均分計算 + sum_dialog: + title: 小總結 + content: 所有科目的GPA:{gpa_all} 所有科目的均分:{avg_all} 所有科目的學分:{credit_all} 未透過科目:{unpassed} + 公共選修課已經修得學分:{not_core_credit} 本程式提供的資料僅供參考,開發者對其準確性不負責 + score_compose_card: + no_detail: 未提供詳情資訊 + fetching: 正在獲取 + credit: 學分 + gpa: GPA + score: 成績 + score_info_card: + title: 成績詳情 + original_course: 初修 + failed: '[掛] ' + credit: 學分 {credit} + gpa: GPA {gpa} + score: 成績 {score} + score_page: + title: 成績查詢 + search_hint: 搜尋成績記錄 + no_record: 未篩查到合請求的記錄 + select_all: 全選 + select_nothing: 全不選 + reset_select: 重置選擇 + CET-4: 國家英語四級 + CET-6: 國家英語六級 +setting: + about: 關於 + about_this_program: 關於本程式 + version: 版本號:{version_code} + user_info: 使用者資訊 + ui_setting: 介面設定 + brightness_setting: 設定深淺色 + simplify_timeline: 簡化日程時間軸 + simplify_timeline_description: 沒有日程時 減少空間佔用 + account_setting: 介面設定 + sport_password_setting: 體育系統密碼設定 + experiment_password_setting: 物理實驗系統密碼設定 + electricity_password_setting: 電費帳號密碼設定 + electricity_password_description: 非 123456 請設定 + classtable_setting: 課表相關設定 + background: 開啟課表背景圖 + no_background: 你先選個圖片罷,就在下面 + choose_background: 課表背景圖選擇 + no_permission: 未獲取儲存許可權,無法讀取檔案 + successful_setting: 設定成功 + failure_setting: 你沒有選圖片捏 + clear_user_class: 清除所有使用者新增課程 + clear_user_class_dialog: + title: 確認對話方塊 + content: 是否要清除所有使用者新增課程?這個功能對從學校獲取的日程沒有影響。 + clear: 已經清除完畢 + class_refresh: 強制重新整理課表 + class_refresh_dialog: + title: 確認對話方塊 + content: 是否要強制重新整理課表?同意後,將會從學校一站式後端重新獲取課表,耗時會比較久。 + class_swift: 課程偏移設定 + class_swift_description: '正數錯後開學日期 負數提前開學日期 + + 目前為 {swift}' + core_setting: 快取登入設定 + check_catcher: 測試錯誤攔截器 + check_logger: 檢視網路攔截器和日誌 + clear_and_restart: 清除快取後重啟 + clear_and_restart_dialog: + title: 確認對話方塊 + content: 確定清除快取後重啟程式? + cleaning: 正在清理快取 + clear: 快取已被清除 + logout: 退出登入並重啟應用 + logout_dialog: + title: 確認對話方塊 + content: 確定退出登入?你的所有資料將會被徹底刪除! + logging_out: 正在退出登入 + need_close_dialog: + title: 請關閉應用 + need_restart_d: 因為技術限制,使用者需要自行關閉視窗,然後重新開啟應用。 + change_brightness_dialog: + title: 顏色設定 + follow_setting: 跟隨系統 + day_mode: 白天模式 + night_mode: 黑夜模式 + change_swift_dialog: + title: 課程偏移設定 + input_hint: 請在此輸入數字 + change_password_dialog: + title: 修改電費帳號密碼 + input_hint: 請在此輸入密碼 + blank_input: 輸入空白! + easter_egg_page: + title: 你找到了彩蛋 + encrypt: 加密上面的文字 + listen: 聽歌時間 + about_page: + benderblog: 主要開發者,iOS 小部件編寫和拼接 + bellssgit: 支援:最佳&最久故障反饋者 + brackrat: 設計:主頁,登入頁,配色,iOS 小部件等 + breezeline: 支援:無價值無意義的產品經理(他自己的描述) + cafebabe: “支援:提供彩蛋程式碼" + chitao1234: 開發:修復滑塊不對齊問題 + dimole: 支援:輔助修復滑塊問題 + elitewars: 設計:體育成績頁面 + hhzm: 支援:提供彩蛋程式碼 + lsy223622: 設計:iOS 圖示 + nancuncloud: 開發:圖書館搜尋功能 + pairman: 開發:成績快取功能和最佳化滑塊演算法 + reverierxu: 設計:用於資訊展示的 ReX 卡片 + ray: 設計:開屏畫面 / 支援:iOS 開發 + stalomeow: 設計:首頁時間軸 / 開發:非同步登入 + xeonds: 設計:設定頁面 / 開發:XDU Planet + xiue233: 開發:Android 小部件和拼接 + zcwzy: 開發:修復丁香電費 / 支援:研究生版本開發 + homepage: 主頁 + code: 開原始碼 + donate: 給我捐款 + know_more: 知道更多 + copyright_notice: 本軟體複製基於 traintime_pda 程式碼(或稱 watermeter 程式碼)編譯, 程式碼按照 Mozilla + Public License, v. 2.0 授權。 本程式和西安電子科技大學,體適能服務,書蝸,電錶等服務無關。 Copyright 2023-Present + BenderBlog Rodriguez and contributors. The Source Code Form is subject to the + terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + beian: 備案號 + sign_android: 安卓簽名 + title: 關於本軟體 +sport: + fetching: 正在獲取 + error: '壞事: {situation}' + title: 體育查詢 + class_info: 課程資訊 + test_score: 體測成績 + total_score: 四年總分 + semester: '{year} 第{gradeType}' + subject: 專案 + data: 資料 + score: 分數 + passed: 及格 + score_string: '{score}分' +toolbox: + title: 其他功能 + payment: 繳費系統 + payment_description: 電費該交了吧 + repair: 後勤報修 + repair_description: 不要漏水斷網 + reserve: 空間預約 + reserve_description: 找個地方打牌 + mobile: 移動門戶 + mobile_description: 請假專用門戶 + network: 網路查詢 + network_description: 希望永不收費 + physics: 物理計算 + physics_description: 希望操作順利 + discover: 睿思導航 + discover_description: 補充其他功能 +xdu_planet: + all: 全部 + loading: 載入中,請稍等 <(=ω=)> + unknown_author: 未知作者 + load_failed: 文章載入失敗,如有需要可以點選右上方的按鈕在瀏覽器裡開啟。 + no_comment: 暫無評論 + reply_audit: '回覆評論 #{reply_to} 已被舉報或刪除' + reply: '回覆評論 #{reply_to}:{content}' + have_been_audit: 本評論已經被舉報 + audit: 舉報 + confirm_audit_dialog: + title: 確認是否舉報 + content: 三思而後行,確定您想舉報嗎?舉報後該評論會有標籤,不一定會刪除。 + ongoing: 正在舉報評論 + failed: 舉報失敗 + success: 舉報成功 + comment: 回覆 + comment_success: 評論成功 + comment_failed: 評論失敗,請去網路檢視器和日誌檢視器檢視報錯 + comment_canceled: 沒想好要說啥嘛 + comment_loading: 載入評論中…… From 2f36e6050cac0165335c5d684ae05af2f22b38c4 Mon Sep 17 00:00:00 2001 From: "BenderBlog \"SuperBart\" Rodriguez" Date: Sat, 12 Oct 2024 13:35:26 +0800 Subject: [PATCH 4/4] feat: underway translation integration --- assets/flutter_i18n/s2cfbb.py | 4 +- assets/flutter_i18n/s2twp.py | 4 +- assets/flutter_i18n/zh_CN.yaml | 145 +++-- assets/flutter_i18n/zh_SG.yaml | 547 +++++++++--------- assets/flutter_i18n/zh_TW.yaml | 204 +++---- lib/main.dart | 3 + lib/model/toolbox_addresses.dart | 54 +- lib/page/creative_job/creative_job.dart | 85 ++- .../creative_job/creative_job_choice.dart | 6 +- .../creative_job_description.dart | 29 +- .../empty_classroom_search_window.dart | 46 +- .../empty_classroom_window.dart | 10 +- lib/page/exam/exam_info_window.dart | 53 +- lib/page/exam/not_arranged_info.dart | 23 +- lib/page/experiment/experiment_info_card.dart | 9 +- lib/page/experiment/experiment_window.dart | 53 +- lib/page/homepage/toolbox/creative_card.dart | 9 +- .../toolbox/empty_classroom_card.dart | 9 +- lib/page/homepage/toolbox/exam_card.dart | 25 +- lib/page/homepage/toolbox/score_card.dart | 9 +- lib/page/library/book_detail_card.dart | 79 ++- lib/page/library/book_info_card.dart | 65 ++- lib/page/library/book_place_card.dart | 19 +- lib/page/library/borrow_info_card.dart | 46 +- lib/page/library/borrow_list_window.dart | 16 +- lib/page/library/library_window.dart | 15 +- lib/page/library/search_book_window.dart | 67 ++- lib/page/login/bottom_buttons.dart | 24 +- lib/page/login/captcha_input_dialog.dart | 29 +- lib/page/login/jc_captcha.dart | 6 +- lib/page/login/login_window.dart | 60 +- lib/page/schoolcard/school_card_window.dart | 56 +- lib/page/setting/about_page/about_page.dart | 402 ++++++++----- .../setting/about_page/easter_egg_page.dart | 169 +++++- .../dialogs/change_brightness_dialog.dart | 27 +- .../setting/dialogs/change_swift_dialog.dart | 23 +- .../dialogs/electricity_password_dialog.dart | 53 +- .../dialogs/experiment_password_dialog.dart | 29 +- .../dialogs/sport_password_dialog.dart | 29 +- lib/page/setting/setting.dart | 320 +++++++--- lib/page/toolbox/toolbox_page.dart | 84 ++- lib/themes/demo_blue.dart | 6 - pubspec.yaml | 4 +- 43 files changed, 1965 insertions(+), 990 deletions(-) diff --git a/assets/flutter_i18n/s2cfbb.py b/assets/flutter_i18n/s2cfbb.py index 44622df2..abb84f66 100644 --- a/assets/flutter_i18n/s2cfbb.py +++ b/assets/flutter_i18n/s2cfbb.py @@ -1,4 +1,5 @@ import yaml +import json import pypinyin from collections import OrderedDict from copy import deepcopy @@ -217,7 +218,8 @@ def recursive_modify(data): # 将修改后的数据保存在新的YAML文件,保持原本的顺序 with open(f"modified_{filename}", 'w', encoding='utf-8') as file: - yaml.dump(modified_data, file, allow_unicode=True, Dumper=OrderedDumper) + json.dump(modified_data, file) + #yaml.dump(modified_data, file, allow_unicode=True, Dumper=OrderedDumper) print(f"Modified YAML saved as 'modified_{filename}'") diff --git a/assets/flutter_i18n/s2twp.py b/assets/flutter_i18n/s2twp.py index ede74153..13a20603 100644 --- a/assets/flutter_i18n/s2twp.py +++ b/assets/flutter_i18n/s2twp.py @@ -18,7 +18,7 @@ def construct_mapping(loader, node): ) # 读取 YAML 文件并保持顺序 -with open('example.yaml', 'r', encoding='utf-8') as file: +with open('zh_CN.yaml', 'r', encoding='utf-8') as file: yaml_content = yaml.load(file, Loader=OrderedLoader) # 遍历 YAML 内容并转换 @@ -45,7 +45,7 @@ def dict_representer(dumper, data): OrderedDumper.add_representer(OrderedDict, dict_representer) # 将转换后的内容写入新的 YAML 文件,并保持顺序 -with open('zh_TW(s2twp).yaml', 'w', encoding='utf-8') as file: +with open('zh_TW.yaml', 'w', encoding='utf-8') as file: yaml.dump(converted_content, file, Dumper=OrderedDumper, allow_unicode=True) print("YAML 文件中的中文已经转换并保持了顺序!") diff --git a/assets/flutter_i18n/zh_CN.yaml b/assets/flutter_i18n/zh_CN.yaml index 64a7216c..2a9464a8 100644 --- a/assets/flutter_i18n/zh_CN.yaml +++ b/assets/flutter_i18n/zh_CN.yaml @@ -6,7 +6,7 @@ drag_text: "上拉请求更多" ready_text: "正在加载......" processing_text: "正在加载......" processed_text: "请求成功" -noMore_text: "数据没有更多" +no_more_text: "数据没有更多" failed_text: "数据获取失败更多" # 公共组件 @@ -44,32 +44,8 @@ login_process: # TODO: ehall_exam_session data # main.dart 里面 Catcher 插件字符串 -catcher: - error_detected: "发生错误" - error_description: "详情如下" - -# 登录界面 -login: - identity_number: "学号" - password: "一站式登录密码" - login: "登录" - incorrect_password_pattern: "用户名或密码不符合要求,学号必须 11 位且密码非空" - on_login_progress: "正在登录学校一站式" - complete_login: "登录成功" - failed_login_cannot_connect_to_server: "无法连接到服务器" - failed_login_with_code: "请求失败,响应状态码:{code}" - failed_login_with_message: "请求失败,报错信息:{message}" - failed_login_other: "未知错误,请联系开发者" - bottom_buttons: - clear_cache: "清除登录缓存" - complete_clear_cache: "清理缓存成功" - see_inspector: "查看网络交互" - captcha_window: - title: "请输入验证码" - hint: "输入验证码" - message_on_empty: "请输入验证码" - slider: - title: "服务器认证服务" +catcher_detected: "发生错误" +catcher_description: "详情如下" # 日程表/课程表 classtable: @@ -113,13 +89,13 @@ classtable: empty_message: "目前没有调课信息" teacher_change: "从{previous_teacher}变为{new_teacher}" no_teacher_change: "教师信息没有改变" - 1: '一' - 2: '二' - 3: '三' - 4: '四' - 5: '五' - 6: '六' - 7: '日' + 1: "一" + 2: "二" + 3: "三" + 4: "四" + 5: "五" + 6: "六" + 7: "日" change_class_message: 调课信息,从第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}节 调整为第{newAffectedWeeksListStr}周星期{weekChar_newWeek}的 @@ -176,15 +152,14 @@ creative_job: no_result: "没有搜索到结果" please_search: "请在上面搜索框搜索" query_for_person: "招募 {exceptNumber} 人 · " - end_time: "截止日期 {end_time}" + end_time: "截止日期 {endTime}" complete_choosing: "选择完毕" - creative_job_description: - title: "工作详情" - browser_hint: "*如果用户感兴趣,请按右上角的按钮在浏览器中打开*" - job_description_title: 岗位描述 - reward_title: 工作回报 - progress_title: 项目进度 - no_description: 没有描述 + job_description: "工作详情" + browser_hint: "如果用户感兴趣,请按右上角的按钮在浏览器中打开" + job_description_title: "岗位描述" + reward_title: "工作回报" + progress_title: "项目进度" + no_description: "没有描述" # 空闲教室 empty_classroom: @@ -232,33 +207,29 @@ homepage: loading: "正在加载" load_error: "加载错误" on_holiday: "假期中" - on_weekday: "第 ${c.getCurrentWeek(updateTime) + 1} 周" + on_weekday: "第 ${current} 周" loading_message: "请稍候,正在刷新信息" homepage: "主页" - xdu_planet: "博客星球" + planet: "博客星球" setting: "设置" input_partner_data: route_not_exist: "导入路径不存在:P" failed_get_file: "导入文件失败" - failed_import: 好像导入文件有点问题:P + failed_import: "好像导入文件有点问题:P" success_message: "导入成功,如果打开了课表页面请重新打开" not_loaded: "还没加载课程表,等会再来吧……" - confirm_dialog: - title: "确认对话框" - content: "目前有搭子课表数据,是否要覆盖?" + confirm_content: "目前有搭子课表数据,是否要覆盖?" login_message: "登录中,暂时显示缓存数据" successful_login_message: "登录成功" - password_wrong_dialog: - title: "用户名或密码有误" - content: "是否重启应用后手动登录?" - confirm: "确认" - denial: "否,进入离线模式" - offline_mode_dialog: - title: 统一认证服务离线模式开启 - content: 无法连接到统一认证服务服务器,所有和其相关的服务暂时不可用。 - 成绩查询,考试信息查询,欠费查询,校园卡查询关闭。课表显示缓存数据。其他功能暂不受影响。 - 如有不便,敬请谅解。 - message: "脱机模式下,一站式相关功能全部禁止使用" + password_wrong_title: "用户名或密码有误" + password_wrong_content: "是否重启应用后手动登录?" + password_wrong_denial: "否,进入离线模式" + offline_mode_title: "统一认证服务离线模式开启" + offline_mode_content: + "无法连接到统一认证服务服务器,所有和其相关的服务暂时不可用。 + 成绩查询,考试信息查询,欠费查询,校园卡查询关闭。课表显示缓存数据。其他功能暂不受影响。 + 如有不便,敬请谅解。" + offline_mode: "脱机模式下,一站式相关功能全部禁止使用" notice_card: empty_notice: "目前没有获取应用公告,请刷新" no_notice_avaliable: "没有获取应用公告" @@ -279,14 +250,11 @@ homepage: title: "电量信息" current_electricity: "目前电量 " kwh: " 度" - dialog: - title: "水电信息" - content: 电费帐号:{account} - 电量信息:{electricityInfo.value} - {electricityInfo} - 欠费信息:{owe_value} - 长按可以重新加载,有欠费一般代表水费 - confirm: "确定" + dialog_title: "水电信息" + dialog_content: "电费帐号:{account} + 电量信息:{value} {electricityInfo} + 欠费信息:{owe_value} + 长按可以重新加载,有欠费一般代表水费" library_card: title: "图书借阅" current_borrow: "目前借书 " @@ -294,7 +262,7 @@ homepage: error_occured: "获取借书信息发生错误" fetching: "正在获取借书信息" no_return: "目前没有待归还书籍" - need_return: "待归还{borrow_info.dued}本书籍" + need_return: "待归还{dued}本书籍" no_info: "目前无法获取信息" fetching_info: "正在查询信息中" school_card_info_card: @@ -325,7 +293,7 @@ library: title: "图书馆信息" borrow_state_title: "借书状态" search_book_title: "查询藏书" - not_provided: "没有相关信息" + not_provided: "未提供相关信息" author: "作者 " publish_house: "出版社 " call_number: "索书号 " @@ -344,13 +312,34 @@ library: cannot_be_renewable: "不可续借" renewing: "正在续借" empty_borrow_list: "目前没有查询到在借图书\n不借书就要变成上面的小呆瓜咯" - borrow_list_info: "在借 {borrowListLength} 本,其中已过期 {duedLength} 本" + borrow_list_info: "在借 {borrow} 本,其中已过期 {dued} 本" search_book_window: search_here: "在此搜索" book_detail: "书籍详细信息" no_result: "没有结果" please_search: "请在上面搜索框搜索" +# 登录界面 +login: + identity_number: "学号" + password: "一站式登录密码" + login: "登录" + incorrect_password_pattern: "用户名或密码不符合要求,学号必须 11 位且密码非空" + on_login_progress: "正在登录学校一站式" + complete_login: "登录成功" + failed_login_cannot_connect_to_server: "无法连接到服务器" + failed_login_with_code: "请求失败,响应状态码:{code}" + failed_login_with_message: "请求失败,报错信息:{message}" + failed_login_other: "未知错误,请联系开发者" + clear_cache: "清除登录缓存" + complete_clear_cache: "清理缓存成功" + see_inspector: "查看网络交互" + captcha_window: + title: "请输入验证码" + hint: "输入验证码" + message_on_empty: "请输入验证码" + slider_title: "服务器认证服务" + # 校园卡流水 school_card_window: title: "校园卡流水信息" @@ -419,7 +408,7 @@ setting: simplify_timeline: "简化日程时间轴" simplify_timeline_description: "没有日程时 减少空间占用" # 账号设置 - account_setting: "界面设置" + account_setting: "账号设置" sport_password_setting: "体育系统密码设置" experiment_password_setting: "物理实验系统密码设置" electricity_password_setting: "电费帐号密码设置" @@ -460,7 +449,7 @@ setting: logging_out: "正在退出登录" need_close_dialog: title: "请关闭应用" - need_restart_d: "因为技术限制,用户需要自行关闭窗口,然后重新打开应用。" + content: "因为技术限制,用户需要自行关闭窗口,然后重新打开应用。" # 剩下乱七八糟的窗口 change_brightness_dialog: title: "颜色设置" @@ -470,8 +459,10 @@ setting: change_swift_dialog: title: "课程偏移设置" input_hint: "请在此输入数字" + change_electricity_title: "修改电费帐号密码" + change_experiment_title: "修改物理实验账号密码" + change_sport_title: "修改体育系统账号密码" change_password_dialog: - title: "修改电费帐号密码" input_hint: "请在此输入密码" blank_input: "输入空白!" easter_egg_page: @@ -487,19 +478,21 @@ setting: chitao1234: "开发:修复滑块不对齐问题" dimole: "支持:辅助修复滑块问题" elitewars: "设计:体育成绩页面" + godhu777777: "支持:繁体中文转换代码和彩蛋代码" + hancl777: "支持:繁体中文转换代码" hhzm: "支持:提供彩蛋代码" lsy223622: "设计:iOS 图标" - nancuncloud: "开发:图书馆搜索功能" + nancunchild: "开发:图书馆搜索功能" pairman: "开发:成绩缓存功能和优化滑块算法" reverierxu: "设计:用于信息展示的 ReX 卡片" - ray: "设计:开屏画面 / 支持:iOS 开发" + ray: "设计:开屏画面 / 支持:iOS 发行商 & 搭子课表" + shadowyingyi: "支持:两次鸽子公众号宣传" stalomeow: "设计:首页时间轴 / 开发:异步登录" xeonds: "设计:设置页面 / 开发:XDU Planet" xiue233: "开发:Android 小部件和拼接" zcwzy: "开发:修复丁香电费 / 支持:研究生版本开发" homepage: "主页" code: "开源代码" - donate: "给我捐款" know_more: "知道更多" copyright_notice: 本软件拷贝基于 traintime_pda 代码(或称 watermeter 代码)编译, diff --git a/assets/flutter_i18n/zh_SG.yaml b/assets/flutter_i18n/zh_SG.yaml index 5ae479ca..f525b31f 100644 --- a/assets/flutter_i18n/zh_SG.yaml +++ b/assets/flutter_i18n/zh_SG.yaml @@ -1,115 +1,90 @@ -# Copyright 2024 BenderBlog Rodriguez and contributors. -# SPDX-License-Identifier: MPL-2.0 - drag_text: 👆拉🌤求更多 -ready_text: 正♻️⛽♻️...... -processing_text: 正♻️⛽♻️...... -processed_text: 🌤求❌功 -noMore_text: 📖🍊没👉更多 -failed_text: 🐀🍊获取Ⅹ败更多 +ready_text: 正♻️🏠♻️...... +processing_text: 正♻️➕♻️...... +processed_text: 🌤求×功 +no_more_text: 📕🍊没🈶更多 +failed_text: 🐀🍊获取⑩败更多 choose_semester: 选择学🚴🏿 -error_detected: ⭕️uch! 发🔊错🈚️啦 +error_detected: 0uch! 发🔊错🈚️啦 click_to_refresh: 点👴刷新 confirm_title: 确认对🌸框 cancel: 取🏫 confirm: 确定 -network_error: 网络错🈚️,可能⑩没联网,可能🪨学🏫服🈚️Ⅶ➗️🧵🤣故障:-P +network_error: 网络错🈚️,可能💩没联网,可能💩学🏫服🈚️Ⅶ➗️🧵🤣故障:-P error_detect: '遇🔪错🈚️: {e}' -query_failed: 查询Ⅹ败 +query_failed: 查询💩败 not_school_network: 没👉♻️🏫园网环🚨 experiment_controller: - no_password: 没🈶🈚️理⑩验密🤱🏻 - login_failed: 🛋️录Ⅹ败 -cancel_exam: 取🏫考💩资格:P + no_password: 没🈶🈚️理🪨验密🤱🏻 + login_failed: 🟰录💩败 +cancel_exam: 取🏫考🪨资格:P electricity_session: fetching: 正♻️获取 not_school_network: 💴🏫园网 network_problem: 网络故障 - query_failed: 查询💩败 + query_failed: 查询🪨败 program_crash: ×序故障 login_process: - ready_page: 准备获取🟰录网页 - get_encrypt: 获取密🤱🏻⛽密密💊 - ready_login: 准备🟰录 + ready_page: 准备获取🛋️录网页 + get_encrypt: 获取密🤱🏻+密密💊 + ready_login: 准备🛋️录 slider: 🌸块验证 - after_process: 🟰录🐒➗️理 + after_process: 🟰录🐒÷理 failed: 🟰录💩败,🐘应状态🤱🏻:{statusCode} -catcher: - error_detected: 发🔊错🈚️ - error_description: 🐘🌤🧴👇 -login: - identity_number: 学号 - password: ①站💩🟰录密🤱🏻 - login: 🟰录 - incorrect_password_pattern: 用🐅名或密🤱🏻⛔符⚛️💊求,学号🖊须 11 位且密🤱🏻💴🈳 - on_login_progress: 正♻️🛋️录学🏫Ⅰ站⑩ - complete_login: 🛋️录❌功 - failed_login_cannot_connect_to_server: 🈚️法连接🔪服🈚️Ⅶ - failed_login_with_code: 🌤求💩败,🐘应状态🤱🏻:{code} - failed_login_with_message: 🌤求Ⅹ败,报错信息:{message} - failed_login_other: 未☞错🈚️,🌤联系🔓发者 - bottom_buttons: - clear_cache: 🌤➗️🟰录缓存 - complete_clear_cache: 🌤理缓存❌功 - see_inspector: 查👀网络🦵🐅 - captcha_window: - title: 🌤🐀🧴验证🤱🏻 - hint: 📖🧴验证🤱🏻 - message_on_empty: 🌤🐀🧴验证🤱🏻 - slider: - title: 服🈚️⑦认证服🈚️ +catcher_detected: 发🔊错🈚️ +catcher_description: 🐘🌤🧴👇 classtable: weekday: - monday: 周Ⅰ + monday: 周🥻 tuesday: 周Ⅱ - wednesday: 周③ - thursday: 周④ + wednesday: 周🥪 + thursday: 周☠️ friday: 周🈚️ - saturday: 周⑥ + saturday: 周Ⅵ sunday: 周日 partner_classtable: - override_dialog: 🤱🏻前🈶🐘子课⌚📕🍊,Ⅹ否💊覆盖❓ + override_dialog: 🤱🏻前👉🐘子课⌚📖🍊,⑩否💊覆盖❓ no_file: 未发🧵🔪🧴文➖ no_permission: 未获取存➗️权🧵,🈚️法读取文➖ problem: 好🐘🔪🧴文➖🈶点问题:P success: 🔪🧴×功 share_dialog: - title: 🌤🖐🏻💊随🥻分🐘 - content: 🔪➗️文➖包括你🉐个人信息,🌤⛔💊随①跟别人分🐘,或者发♻️🐘群里。 + title: 🌤🖐🏻💊随①分🐘 + content: 🔪➗️文➖包括你🉐个人信息,🌤🚫💊随➖跟别人分🐘,或者发♻️🐘群里。 save_dialog: title: 保存日历文➖🔪... - success_message: 应该保存❌功 - failure_message: 文➖创➖⑩败,保存取🏫 + success_message: 应该保存×功 + failure_message: 文➖创➖💩败,保存取🏫 delete_dialog: title: 确认对🌸框 - message: 确定💊🌤➗️共🐘课⌚🤱🏻❓ - success_message: 删➗️共🐘课⌚✖功 - page_title: 👴🉐日❌⌚ + message: 确定💊🌤÷共🐘课⌚🤱🏻❓ + success_message: 删➗️共🐘课⌚×功 + page_title: 👴🉐日×⌚ partner_page_title: 🐘子🉐日×⌚ popup_menu: not_arranged: 查👀未安排课✖信息 - class_changed: 查👀课×安排调整信息 + class_changed: 查👀课❌安排调整信息 add_class: 添+课×信息 generate_ical: 🔊×日历文➖ generate_partner_file: 🔊❌共🐘课⌚文➖ import_partner_file: 🔪🧴共🐘课⌚文➖ - delete_partner_file: 删➗️共🐘课⌚文➖ + delete_partner_file: 删÷共🐘课⌚文➖ class_change_page: - title: 课×调整 - empty_message: 🤱🏻前没👉调课信息 + title: 课✖调整 + empty_message: 🤱🏻前没🈶调课信息 teacher_change: 从{new_teacher}变为{new_teacher} - no_teacher_change: 🔈Ⅹ信息没👉改变 - 1: 🥻 + no_teacher_change: 🎺💩信息没👉改变 + 1: ① 2: 👂🏻 - 3: 📐 - 4: Ⅳ + 3: ③ + 4: ④ 5: 🈚️ - 6: Ⅵ + 6: ⑥ 7: 日 - change_class_message: 调课信息,从第{newClassroom}周 星Ⅶ{newClassroom}🉐{newClassroom}-{newClassroom}节 - 调整为第{newClassroom}周星🚴🏿{newClassroom}🉐 {newClassroom}-{newClassroom}节,{newClassroom}🎺Ⅹ👆课 - patch_class_message: ⛔课信息,从第{newClassroom}周 星🚴🏿{newClassroom}🉐{newClassroom}-{newClassroom}节, - {newClassroom}🖐🏻课 + change_class_message: 调课信息,从第{newClassroom}周 星⑦{newClassroom}🉐{newClassroom}-{newClassroom}节 + 调整为第{newClassroom}周星🚴🏿{newClassroom}🉐 {newClassroom}-{newClassroom}节,{newClassroom}🔈⑩👆课 + patch_class_message: 🚫课信息,从第{newClassroom}周 星⑦{newClassroom}🉐{newClassroom}-{newClassroom}节, + {newClassroom}⛔课 stop_class_message: 停课信息,第{originalClassroom}周 星🚴🏿{originalClassroom}🉐{originalClassroom}-{originalClassroom}节 {originalClassroom}停课 class_info: '编号: {teacherChange} | {teacherChange} 班 @@ -118,130 +93,124 @@ classtable: {teacherChange}' not_arranged_page: - title: 没🈶⑩➖安排🉐科🤱🏻 - empty_message: 🤱🏻前全⛔课×均👉🪨➖安排 + title: 没👉Ⅹ➖安排🉐科🤱🏻 + empty_message: 🤱🏻前全🖐🏻课❌均🈶⑩➖安排 content: '编号: {teacher} | {teacher} 班 老🪨: {teacher}' - empty_class_message: '{semester_code} 学🚴🏿没👉课✖' + empty_class_message: '{semester_code} 学🚴🏿没🈶课✖' week_title: 第{week}周 noon_break: 🈚️休 supper_break: 晚休 class_card: - title: 日×信息 - unknown_classroom: 未🈯🦵⑩ - remains_hint: 还👉{remain_count}个日❌ + title: 日✖信息 + unknown_classroom: 未🧻🗣💩 + remains_hint: 还🈶{remain_count}个日× class_add: - add_class_title: 添+课× - change_class_title: 修改课❌ - class_name_empty_message: 🖊须📖🧴课❌名 - wrong_time_message: 📖🧴🉐Ⅹ➖🖐🏻对 + add_class_title: 添➕课× + change_class_title: 修改课× + class_name_empty_message: 🖊须🐀🧴课×名 + wrong_time_message: 📖🧴🉐💩➖⛔对 save_button: 保存 - input_classname_hint: 课✖名字(🖊填) - input_teacher_hint: 老Ⅹ姓名(选填) - input_classroom_hint: 🗣Ⅹ位☞(选填) + input_classname_hint: 课×名字(🖊填) + input_teacher_hint: 老⑩姓名(选填) + input_classroom_hint: 🗣🪨位📃(选填) input_week_hint: 选择👆课周次 - input_time_hint: 选择👆课💩➖ + input_time_hint: 选择👆课🪨➖ input_time_weekday_hint: 👆课周次 - input_start_time_hint: 👆课⑩➖段 - input_end_time_hint: 👇课Ⅹ➖段 + input_start_time_hint: 👆课💩➖段 + input_end_time_hint: 👇课🪨➖段 wheel_choose_hint: 第 {index} 节 course_detail_card: class_number_string: '{number} 班' - unknown_teacher: 老⑩未定 + unknown_teacher: 老🪨未定 unknown_place: 地点未定 class_period: '{stop}-{stop}节' edit: 编✈️ - delete: 删÷ - delete_title: 💩否删➗️课×信息❓ - delete_content: 🔒👉📴于这个课🉐信息都🩶被删÷,课⌚👆📴于这🚪课🉐信息将⛔复存♻️! + delete: 删➗️ + delete_title: 🪨否删➗️课✖信息❓ + delete_content: 🔒🈶📴于这个课🉐信息都🩶被删÷,课⌚👆📴于这🚪课🉐信息将⛔复存♻️! creative_job: search_hint: 搜🔒需求 choice_type: 选择🀄️类 - position_type: 🧻位类型 - no_result: 没👉搜🔒🔪结🍎 + position_type: ☞位类型 + no_result: 没🈶搜🔒🔪结🍎 please_search: 🌤♻️👆面搜🔒框搜🔒 query_for_person: '招🤱🏻 {exceptNumber} 人 · ' - end_time: 截☞日⑦ {end_time} + end_time: 截🈯日⑦ {endTime} complete_choosing: 选择完🖊 - creative_job_description: - title: 工👈🐘🌤 - browser_hint: '*🧴🍎用🐅感兴趣,🌤按🈶👆🦵🉐按🐂♻️Ⅵ览🚴🏿🀄️🐘🔓*' - job_description_title: 岗位描📕 - reward_title: 工👈🩶报 - progress_title: 🐘🤱🏻进度 - no_description: 没🈶描🐀 + job_description: 工👈🐘🌤 + browser_hint: 🧴🍎用🐅感兴趣,🌤按👉👆🗣🉐按🐂♻️⑥览🚴🏿🀄️🐘🔓 + job_description_title: 岗位描🐀 + reward_title: 工👈🩶报 + progress_title: 🐘🤱🏻进度 + no_description: 没👉描🐀 empty_classroom: - title: 🈳🧵🗣⑩ - date: 日Ⅶ {date} + title: 🈳🧵🗣💩 + date: 日⑦ {date} building: 🎺学楼 {building} - search_hint: 🗣🪨名✖或者🎺Ⅹ代🤱🏻 - classroom: 🦵🪨 + search_hint: 🦵💩名×或者🗣💩代🤱🏻 + classroom: 🦵⑩ exam: title: 考🪨安排 - cache_hint: 🥻🧵⑩缓存考⑩安排信息 - not_finished: 未完❌考💩 - all_finished: 🔒🈶考⑩全⛔完❌ - unable_to_exam: 🈚️法完✖考Ⅹ - finished: ①完❌考💩 - none_finished: ①🚪还没考呢 - no_exam_arrangement: 🤱🏻前没👉考💩安排 + cache_hint: 🥻🧵🪨缓存考💩安排信息 + not_finished: 未完✖考⑩ + all_finished: 🔒🈶考⑩全🖐🏻完✖ + unable_to_exam: 🈚️法完❌考⑩ + finished: ➖完❌考Ⅹ + none_finished: 🥻🚪还没考呢 + no_exam_arrangement: 🤱🏻前没🈶考🪨安排 no_arrangement: - title: 🤱🏻前🈚️安排考💩🉐科🤱🏻 - all_arranged: 🤱🏻前🔒👉科🤱🏻均①安排考⑩ + title: 🤱🏻前🈚️安排考🪨🉐科🤱🏻 + all_arranged: 🤱🏻前🔒🈶科🤱🏻均➖安排考⑩ subtitle: '编号: {id}' experiment: - title: 🈚️理Ⅹ验 - ongoing: 正♻️进行⑩验 + title: 🈚️理🪨验 + ongoing: 正♻️进行Ⅹ验 not_finished: 未完✖⑩验 - all_finished: 🔒🈶💩验全🖐🏻完❌ - finished: ➖完×Ⅹ验 - score_sum: 🤱🏻前分📖总⚛️:{sum} - none_finished: 🤱🏻前没👉Ⅰ🚨完❌🉐⑩验 + all_finished: 🔒🈶Ⅹ验全🚫完❌ + finished: Ⅰ完❌💩验 + score_sum: 🤱🏻前分🐀总⚛️:{sum} + none_finished: 🤱🏻前没🈶➖🚨完❌🉐⑩验 not_provided: 未提供 homepage: time_string: - morning: 早👆好 准备÷发 - before_noon: 👆🈚️好 🐖万💩🧴🥻 - at_noon: 🀄️🈚️好 Ⅰ切还好⑧ + morning: 早👆好 准备➗️发 + before_noon: 👆🈚️好 🐖万Ⅹ🧴Ⅰ + at_noon: 🀄️🈚️好 ①切还好⑧ afternoon: 👇🈚️好 今天🧴⚛️ night: 晚👆好 🐖你好梦 midnight: 深🏫🤣 👴♻️陪你 loading: 正♻️🏠♻️ load_error: ⛽♻️错🈚️ - on_holiday: ➕Ⅶ🀄️ - on_weekday: 第 ${c.getCurrentWeek(updateTime) + 1} 周 + on_holiday: +🚴🏿🀄️ + on_weekday: 第 ${current} 周 loading_message: 🌤稍🐒,正♻️刷新信息 homepage: 🐖页 - xdu_planet: 博客星球 - setting: 🐍☞ + planet: 博客星球 + setting: 🐍🧻 input_partner_data: - route_not_exist: 🔪🧴路🚨⛔存♻️:P - failed_get_file: 🔪🧴文➖🪨败 + route_not_exist: 🔪🧴路🚨🚫存♻️:P + failed_get_file: 🔪🧴文➖Ⅹ败 failed_import: 好🐘🔪🧴文➖👉点问题:P - success_message: 🔪🧴✖功,🧴🍎🐘🔓🤣课⌚页面🌤🀄️新🐘🔓 - not_loaded: 还没➕♻️课❌⌚,🟰🩶♻️来Ⅷ…… - confirm_dialog: - title: 确认对🌸框 - content: 🤱🏻前👉🐘子课⌚📖🍊,⑩否💊覆盖❓ - login_message: 🛋️录🀄️,暂Ⅹ🧵⑩缓存📖🍊 - successful_login_message: 🛋️录❌功 - password_wrong_dialog: - title: 用🐅名或密🤱🏻🈶🈚️ - content: Ⅹ否🀄️🚴🏿应用🐒🖐🏻🕳🟰录❓ - confirm: 确认 - denial: 否,进🧴离🧵👺🪨 - offline_mode_dialog: - title: 统①认证服🈚️离🧵👺Ⅹ🔓Ⅶ - content: 🈚️法连接🔪统Ⅰ认证服🈚️服🈚️🚴🏿,🔒🈶⚛️Ⅶ🐘📴🉐服🈚️暂💩🖐🏻可用。 ❌✈️查询,考⑩信息查询,欠💴查询,🏫园卡查询📴🖊。课⌚🧵⑩缓存📕🍊。⑦他功能暂🚫📻影🐘。 - 🧴🈶🖐🏻便,🚨🌤谅解。 - message: 脱✈️👺⑩👇,🥻站💩🐘📴功能全🖐🏻禁🈯Ⅹ用 + success_message: 🔪🧴×功,🧴🍎🐘🔓🤣课⌚页面🌤🀄️新🐘🔓 + not_loaded: 还没⛽♻️课❌⌚,🟰🩶♻️来⑧…… + confirm_content: 🤱🏻前👉🐘子课⌚📕🍊,Ⅹ否💊覆盖❓ + login_message: 🛋️录🀄️,暂💩🧵🪨缓存📖🍊 + successful_login_message: 🟰录❌功 + password_wrong_title: 用🐅名或密🤱🏻🈶🈚️ + password_wrong_content: ⑩否🀄️🚴🏿应用🐒🖐🏻🕳🛋️录❓ + password_wrong_denial: 否,进🧴离🧵👺🪨 + offline_mode_title: 统Ⅰ认证服🈚️离🧵👺Ⅹ🔓Ⅶ + offline_mode_content: 🈚️法连接🔪统Ⅰ认证服🈚️服🈚️🚴🏿,🔒🈶⚛️Ⅶ🐘📴🉐服🈚️暂🪨🖐🏻可用。 ×✈️查询,考💩信息查询,欠💴查询,🏫园卡查询📴🖊。课⌚🧵⑩缓存🐀🍊。Ⅶ他功能暂🚫🖐🏻影🐘。 + 🧴🈶🖐🏻便,🚨🌤谅解。 + offline_mode: 脱✈️👺Ⅹ👇,➖站Ⅹ🐘📴功能全🖐🏻禁📃🪨用 notice_card: empty_notice: 🤱🏻前没🈶获取应用公⛏,🌤刷新 - no_notice_avaliable: 没👉获取应用公⛏ + no_notice_avaliable: 没🈶获取应用公⛏ notice_list_title: 应用信息 open_url: ◻️问该链接 - notice_page_title: 通🧻列⌚ + notice_page_title: 通🈯列⌚ class_table_card: current: 当前 tomorrow: 明天 @@ -250,269 +219,291 @@ homepage: error_message: 遇🔪错🈚️:{error} fetching_message: 正♻️获取课⌚ error_infoText: 遇🔪错🈚️ - fetching_infoText: 正♻️+♻️ + fetching_infoText: 正♻️⛽♻️ no_arrangement_infoText: 暂🈚️日× electricity_card: title: 电量信息 current_electricity: '🤱🏻前电量 ' kwh: ' 度' - dialog: - title: 水电信息 - content: 电💴帐号:{owe_value} 电量信息:{owe_value} {owe_value} 欠💴信息:{owe_value} 长按可Ⅰ🀄️新🏠♻️,👉欠💴Ⅰ般代⌚水💴 - confirm: 确定 + dialog_title: 水电信息 + dialog_content: 电💴帐号:{owe_value} 电量信息:{owe_value} {owe_value} 欠💴信息:{owe_value} + 长按可🥻🀄️新➕♻️,👉欠💴Ⅰ般代⌚水💴 library_card: title: 🐇📕借阅 - current_borrow: '🤱🏻前借🐀 ' - unit_of_book: ' 📕' - error_occured: 获取借🐀信息发🔊错🈚️ + current_borrow: '🤱🏻前借📕 ' + unit_of_book: ' 📖' + error_occured: 获取借📖信息发🔊错🈚️ fetching: 正♻️获取借📕信息 no_return: 🤱🏻前没👉待归还🐀🐔 - need_return: 待归还{borrow_info.dued}📖🐀🐔 + need_return: 待归还{dued}📖📕✈️ no_info: 🤱🏻前🈚️法获取信息 fetching_info: 正♻️查询信息🀄️ school_card_info_card: error_toast: 遇🔪错🈚️,🌤联系🔓发者 fetching_toast: 正♻️获取信息,🌤稍🐒♻️来👀 - bill: ⑥水 + bill: Ⅵ水 balance: '🏫园卡余额 ' unit: ' 元' error_occured: 获取🏫园卡信息发🔊错🈚️ fetching: 正♻️获取🏫园卡信息 - bottom_text_success: 查询Ⅰ卡通⑥水 + bottom_text_success: 查询➖卡通Ⅵ水 no_info: 🤱🏻前🈚️法获取信息 fetching_info: 正♻️查询信息🀄️ toolbox: creative: 双创🚨赛 - empty_classroom: 🈳🧵🎺💩 - exam: 考Ⅹ安排 + empty_classroom: 🈳🧵🗣🪨 + exam: 考💩安排 experiment: 🈚️理💩验 - score: ×🐔查询 + score: ✖🐔查询 sport: 体育信息 - toolbox: 🚴🏿他功能 - score_cannot_reach: 脱✈️状态且🈚️缓存×✈️📖🍊,🈚️法◻️问 - exam_fetching: 🌤稍🐒,正♻️获取考⑩信息 + toolbox: Ⅶ他功能 + score_cannot_reach: 脱✈️状态且🈚️缓存✖✈️🐀🍊,🈚️法◻️问 + exam_fetching: 🌤稍🐒,正♻️获取考Ⅹ信息 exam_error: 遇🔪错🈚️,🌤联系🔓发者 library: - title: 🐇📕📴信息 - borrow_state_title: 借🐀状态 + title: 🐇🐀📴信息 + borrow_state_title: 借📖状态 search_book_title: 查询藏🐀 - not_provided: 没👉🐘📴信息 + not_provided: 未提供🐘📴信息 author: '👈者 ' publish_house: '➗️版🐍 ' - call_number: '🔒📖号 ' - publish_date: '发行💩➖ ' - isbn: 1SBN + call_number: '🔒📕号 ' + publish_date: '发行🪨➖ ' + isbn: I5BN arrangement_code: '编排号🤱🏻 ' avaliable_borrow: 可借 storage: 📴藏 on_shelve: ♻️🏠 - book_code: 🐀✈️编号:{barCode} - due_date: ' 🔪🚴🏿' + book_code: 📖🐔编号:{barCode} + due_date: ' 🔪Ⅶ' borrow_str: ' 借阅' - after_due_date: ' 天前🔪⑦' + after_due_date: ' 天前🔪Ⅶ' before_due_date: ' 天🐒' can_be_renewable: 续借 - cannot_be_renewable: 🚫可续借 + cannot_be_renewable: 🖐🏻可续借 renewing: 正♻️续借 - empty_borrow_list: '🤱🏻前没👉查询🔪♻️借🐇📖 + empty_borrow_list: '🤱🏻前没👉查询🔪♻️借🐇🐀 - 🚫借🐀🍷💊变❌👆面🉐🏫呆瓜咯' - borrow_list_info: ♻️借 {duedLength} 📖,⑦🀄️①🍎🚴🏿 {duedLength} 📖 + ⛔借📕Ⅸ💊变❌👆面🉐🏫呆瓜咯' + borrow_list_info: ♻️借 {dued} 📕,🚴🏿🀄️①🍎🚴🏿 {dued} 📕 search_book_window: null search_here: ♻️此搜🔒 - book_detail: 📖✈️🐘细信息 - no_result: 没👉结🍎 + book_detail: 🐀🐔🐘细信息 + no_result: 没🈶结🍎 please_search: 🌤♻️👆面搜🔒框搜🔒 +login: + identity_number: 学号 + password: ➖站⑩🟰录密🤱🏻 + login: 🛋️录 + incorrect_password_pattern: 用🐅名或密🤱🏻🖐🏻符⚛️💊求,学号🖊须 11 位且密🤱🏻💴🈳 + on_login_progress: 正♻️🛋️录学🏫➖站💩 + complete_login: 🛋️录❌功 + failed_login_cannot_connect_to_server: 🈚️法连接🔪服🈚️🚴🏿 + failed_login_with_code: 🌤求🪨败,🐘应状态🤱🏻:{code} + failed_login_with_message: 🌤求⑩败,报错信息:{message} + failed_login_other: 未📃错🈚️,🌤联系🔓发者 + clear_cache: 🌤➗️🛋️录缓存 + complete_clear_cache: 🌤理缓存❌功 + see_inspector: 查👀网络🦵🐅 + captcha_window: + title: 🌤📖🧴验证🤱🏻 + hint: 📕🧴验证🤱🏻 + message_on_empty: 🌤📕🧴验证🤱🏻 + slider_title: 服🈚️Ⅶ认证服🈚️ school_card_window: title: 🏫园卡Ⅵ水信息 - income: ☞➗️ {income} - expense: 📻🧴 {expense} - select_range: 选择日🚴🏿:从 {endDay} 🔪 {endDay} + income: 🧻÷ {income} + expense: 🖐🏻🧴 {expense} + select_range: 选择日⑦:从 {endDay} 🔪 {endDay} store_name: 👆🐅名✖ balance: 金额 - time_with_sum: 🪨➖(共{sum}元) + time_with_sum: ⑩➖(共{sum}元) score: - title: ❌✈️查询 - cache_message: Ⅰ🧵💩缓存✖🐔信息 - all_semester: 🔒👉学🚴🏿 - chosen_semester: 学⑦ {chosen} + title: ×✈️查询 + cache_message: ①🧵🪨缓存✖✈️信息 + all_semester: 🔒🈶学Ⅶ + chosen_semester: 学🚴🏿 {chosen} all_type: 🔒🈶类型 chosen_type: 类型 {type} score_choice: - title: ×✈️单 - search_hint: 搜🔒❌🐔✈️录 - empty_list: 没👉选择该学⑦🉐课❌✈️🧴均分✈️🍋 + title: ×🐔单 + search_hint: 搜🔒❌✈️✈️录 + empty_list: 没🈶选择该学Ⅶ🉐课❌🐔🧴均分✈️🍋 sum_dialog: title: 🏫总结 - content: 🔒👉科🤱🏻🉐9P4:{not_core_credit} 🔒🈶科🤱🏻🉐均分:{not_core_credit} 🔒🈶科🤱🏻🉐学分:{not_core_credit} - 未通🍎科🤱🏻:{not_core_credit} 公共选修课①🚨修🉐学分:{not_core_credit} 📖×序提供🉐📖🍊仅供参考,🔓发者对🚴🏿准确性🖐🏻负责 + content: 🔒🈶科🤱🏻🉐9P4:{not_core_credit} 🔒👉科🤱🏻🉐均分:{not_core_credit} 🔒🈶科🤱🏻🉐学分:{not_core_credit} + 未通🍎科🤱🏻:{not_core_credit} 公共选修课①🚨修🉐学分:{not_core_credit} 📖❌序提供🉐📖🍊仅供参考,🔓发者对Ⅶ准确性⛔负责 score_compose_card: no_detail: 未提供🐘🌤信息 fetching: 正♻️获取 credit: 学分 gpa: 9P4 - score: ✖✈️ + score: ✖🐔 score_info_card: - title: ×✈️🐘🌤 + title: ❌🐔🐘🌤 original_course: ➗️修 failed: '[挂] ' credit: 学分 {credit} gpa: 9P4 {gpa} - score: ✖🐔 {score} + score: ❌✈️ {score} score_page: - title: ×✈️查询 - search_hint: 搜🔒×🐔🐔录 - no_record: 未筛查🔪⚛️🌤求🉐✈️录 + title: ×🐔查询 + search_hint: 搜🔒×✈️✈️录 + no_record: 未筛查🔪⚛️🌤求🉐🐔录 select_all: 全选 select_nothing: 全⛔选 - reset_select: 🀄️🧻选择 - CET-4: 🍎⛽英语Ⅳ🐔 + reset_select: 🀄️☞选择 + CET-4: 🍎➕英语Ⅳ✈️ CET-6: 🍎🏠英语⑥✈️ setting: about: 📴于 - about_this_program: 📴于📖✖序 - version: 版📖号:{version_code} + about_this_program: 📴于📕✖序 + version: 版📕号:{version_code} user_info: 用🐅信息 ui_setting: 界面🐍📃 brightness_setting: 🐍📃深浅色 - simplify_timeline: ➖🌸日✖⑩➖轴 - simplify_timeline_description: 没🈶日✖⑩ ➖少🈳➖占用 - account_setting: 界面🐍🧻 - sport_password_setting: 体育系统密🤱🏻🐍☞ - experiment_password_setting: 🈚️理⑩验系统密🤱🏻🐍🧻 - electricity_password_setting: 电💴帐号密🤱🏻🐍🧻 - electricity_password_description: 💴 123456 🌤🐍🧻 - classtable_setting: 课⌚🐘📴🐍☞ + simplify_timeline: ➖🌸日×🪨➖轴 + simplify_timeline_description: 没👉日×🪨 ➖少🈳➖占用 + account_setting: 账号🐍☞ + sport_password_setting: 体育系统密🤱🏻🐍🧻 + experiment_password_setting: 🈚️理💩验系统密🤱🏻🐍☞ + electricity_password_setting: 电💴帐号密🤱🏻🐍📃 + electricity_password_description: 💴 123456 🌤🐍🈯 + classtable_setting: 课⌚🐘📴🐍📃 background: 🔓🚴🏿课⌚背🚨🐇 - no_background: 你🧵选个🐇片👨🏻,Ⅸ♻️👇面 + no_background: 你🧵选个🐇片Ⅷ,⑨♻️👇面 choose_background: 课⌚背🚨🐇选择 no_permission: 未获取存➗️权🧵,🈚️法读取文➖ successful_setting: 🐍定❌功 failure_setting: 你没🈶选🐇片捏 - clear_user_class: 🌤➗️🔒👉用🐅添🏠课❌ + clear_user_class: 🌤➗️🔒👉用🐅添⛽课✖ clear_user_class_dialog: title: 确认对🌸框 - content: 💩否💊🌤÷🔒👉用🐅添⛽课❌❓这个功能对从学🏫获取🉐日×没🈶影🐘。 - clear: ①🚨🌤➗️完🖊 + content: Ⅹ否💊🌤➗️🔒🈶用🐅添➕课❌❓这个功能对从学🏫获取🉐日×没🈶影🐘。 + clear: ➖🚨🌤➗️完🖊 class_refresh: 强🧻刷新课⌚ class_refresh_dialog: title: 确认对🌸框 - content: 🪨否💊强🈯刷新课⌚❓同①🐒,将🩶从学🏫①站🪨🐒端🀄️新获取课⌚,耗💩🩶🖊🎺⑨。 - class_swift: 课✖偏🥻🐍🈯 - class_swift_description: '正📖错🐒🔓学日🚴🏿 负🐀提前🔓学日⑦ + content: 🪨否💊强☞刷新课⌚❓同①🐒,将🩶从学🏫➖站Ⅹ🐒端🀄️新获取课⌚,耗🪨🩶🖊🎺Ⅸ。 + class_swift: 课✖偏①🐍📃 + class_swift_description: '正📕错🐒🔓学日⑦ 负🐀提前🔓学日⑦ 🤱🏻前为 {swift}' - core_setting: 缓存🟰录🐍📃 - check_catcher: 🚻🪨错🈚️拦截Ⅶ - check_logger: 查👀网络拦截🚴🏿⚛️日☞ - clear_and_restart: 🌤÷缓存🐒🀄️⑦ + core_setting: 缓存🛋️录🐍🈯 + check_catcher: 🚻💩错🈚️拦截Ⅶ + check_logger: 查👀网络拦截🚴🏿⚛️日🧻 + clear_and_restart: 🌤➗️缓存🐒🀄️Ⅶ clear_and_restart_dialog: title: 确认对🌸框 - content: 确定🌤➗️缓存🐒🀄️⑦×序❓ + content: 确定🌤➗️缓存🐒🀄️Ⅶ×序❓ cleaning: 正♻️🌤理缓存 - clear: 缓存Ⅰ被🌤➗️ - logout: 退➗️🛋️录并🀄️Ⅶ应用 + clear: 缓存①被🌤➗️ + logout: 退÷🛋️录并🀄️⑦应用 logout_dialog: title: 确认对🌸框 - content: 确定退÷🛋️录❓你🉐🔒👉📖🍊将🩶被彻底删➗️! - logging_out: 正♻️退÷🟰录 + content: 确定退÷🟰录❓你🉐🔒🈶📖🍊将🩶被彻底删÷! + logging_out: 正♻️退➗️🛋️录 need_close_dialog: title: 🌤📴🖊应用 - need_restart_d: 因为✈️📕🧵☞,用🐅需💊自行📴🖊窗口,🔥🐒🀄️新🐘🔓应用。 + content: 因为🐔🐀🧵☞,用🐅需💊自行📴🖊窗口,🔥🐒🀄️新🐘🔓应用。 change_brightness_dialog: - title: 颜色🐍☞ + title: 颜色🐍🈯 follow_setting: 跟随系统 day_mode: 白天👺⑩ - night_mode: 👨🏿夜👺🪨 + night_mode: 👨🏿夜👺Ⅹ change_swift_dialog: - title: 课❌偏🥻🐍☞ - input_hint: 🌤♻️此🐀🧴📕字 + title: 课❌偏🥻🐍🧻 + input_hint: 🌤♻️此📕🧴📖字 + change_electricity_title: 修改电💴帐号密🤱🏻 + change_experiment_title: 修改🈚️理💩验账号密🤱🏻 + change_sport_title: 修改体育系统账号密🤱🏻 change_password_dialog: - title: 修改电💴帐号密🤱🏻 - input_hint: 🌤♻️此📖🧴密🤱🏻 + input_hint: 🌤♻️此📕🧴密🤱🏻 blank_input: 🐀🧴🈳白! easter_egg_page: - title: 你找🔪🤣👎蛋 - encrypt: 🏠密👆面🉐文📕 - listen: 听歌🪨➖ + title: 你找🔪🤣🥬蛋 + encrypt: ➕密👆面🉐文📕 + listen: 听歌Ⅹ➖ about_page: - benderblog: 🐖💊🔓发者,105 🏫🚫➖编写⚛️拼接 - bellssgit: ☞持:最⛽&最Ⅸ故障反馈者 - brackrat: 🐍✈️:🐖页,🟰录页,配色,1OS 🏫⛔➖🛋️ - breezeline: 📃持:🈚️➕☞🈚️➖Ⅰ🉐产品🚨理(他自🐔🉐描🐀) - cafebabe: “🈯持:提供👎蛋代🤱🏻" - chitao1234: 🔓发:修复🌸块🖐🏻对⑦问题 - dimole: 🈯持:辅🐖修复🌸块问题 - elitewars: 🐍🐔:体育✖🐔页面 - hhzm: ☞持:提供🥬蛋代🤱🏻 + benderblog: 🐖💊🔓发者,1⭕️5 🏫🖐🏻➖编写⚛️拼接 + bellssgit: ☞持:最➕&最Ⅸ故障反馈者 + brackrat: 🐍🐔:🐖页,🟰录页,配色,iO5 🏫🖐🏻➖🛋️ + breezeline: 🈯持:🈚️➕🧻🈚️①Ⅰ🉐产品🚨理(他自✈️🉐描📖) + cafebabe: “☞持:提供🥬蛋代🤱🏻" + chitao1234: 🔓发:修复🌸块🚫对⑦问题 + dimole: ☞持:辅🐖修复🌸块问题 + elitewars: 🐍✈️:体育×🐔页面 + godhu777777: 📃持:繁体🀄️文转换代🤱🏻⚛️👎蛋代🤱🏻 + hancl777: 📃持:繁体🀄️文转换代🤱🏻 + hhzm: 🧻持:提供👎蛋代🤱🏻 lsy223622: 🐍✈️:1⭕️5 🐇⌚ - nancuncloud: 🔓发:🐇🐀📴搜🔒功能 - pairman: 🔓发:✖🐔缓存功能⚛️👉🌸🌸块🍋法 + nancunchild: 🔓发:🐇📖📴搜🔒功能 + pairman: 🔓发:×🐔缓存功能⚛️🈶🌸🌸块🍋法 reverierxu: 🐍✈️:用于信息展💩🉐 R3X 卡片 - ray: 🐍🐔:🔓屏🌸面 / 🧻持:i⭕️5 🔓发 - stalomeow: 🐍✈️:📻页⑩➖轴 / 🔓发:①⛔🛋️录 - xeonds: 🐍🐔:🐍☞页面 / 🔓发:XDU Pl4n37 - xiue233: 🔓发:Andro1d 🏫🚫➖⚛️拼接 - zcwzy: 🔓发:修复丁🐘电💴 / 🈯持:研⑨🔊版📖🔓发 + ray: 🐍🐔:🔓屏🌸面 / ☞持:10S 发行👆 & 🐘子课⌚ + shadowyingyi: 🧻持:两次鸽子公🀄️号宣传 + stalomeow: 🐍🐔:🖐🏻页💩➖轴 / 🔓发:①🖐🏻🛋️录 + xeonds: 🐍✈️:🐍📃页面 / 🔓发:XDU P14n37 + xiue233: 🔓发:Andr01d 🏫🚫➖⚛️拼接 + zcwzy: 🔓发:修复丁🐘电💴 / 📃持:研🍷🔊版📖🔓发 homepage: 🐖页 code: 🔓源代🤱🏻 - donate: 给👴捐款 know_more: 📃🔪更多 - copyright_notice: 📕软➖拷贝✈️于 7ra1n7ime_pda 代🤱🏻(或❌ wa73rm373r 代🤱🏻)编①, 代🤱🏻按照 M⭕️z1114 - Pub11c 11c3n53, v. 2.0 🖐🏻权。 📖✖序⚛️西安电子科🐔🐘学,体🪨能服🈚️,🐀蜗,电⌚🟰服🈚️🈚️📴。 C⭕️pyr1gh7 2023-Pr353nt - B3nd3rB1⭕️9 R0dr19u3z 4nd c0n7r1bu7⭕️r5. 7h3 5ourc3 Cod3 F0rm is 5ubj3c7 t0 - th3 7erm5 0f 7h3 M0z1114 Pub11c Lic3n53, v. 2.0. 1f 4 c⭕️py ⭕️f 7h3 MP1 w45 - n0t d1s7r1bu73d w17h 7h15 fi13, Y0u can 0b74in 0n3 4t h77ps://moz11l4.0r9/MP1/2.0/. + copyright_notice: 📖软➖拷贝🐔于 tr41n71m3_pd4 代🤱🏻(或× w473rme73r 代🤱🏻)编🥻, 代🤱🏻按照 M⭕️z11l4 + Pub1ic 1ic3ns3, v. 2.0 📻权。 📕×序⚛️西安电子科✈️🐘学,体⑩能服🈚️,🐀蜗,电⌚🛋️服🈚️🈚️📴。 C⭕️pyr19h7 2023-Pr353n7 + B3nd3rB1⭕️9 R⭕️dr1gu3z and c⭕️n7r1bu7ors. 7h3 5ourc3 Code Form 15 5ubj3c7 to + 7h3 73rm5 of 7h3 Moz1l14 Pub11c 11c3n53, v. 2.0. 1f 4 copy ⭕️f 7h3 MP1 w45 n07 + d157r1bu73d wi7h 7hi5 fi13, Y⭕️u c4n 0b741n ⭕️n3 47 h77ps://m⭕️z1l1a.or9/MP1/2.0/. beian: 备案号 sign_android: 安卓签名 title: 📴于📕软➖ sport: fetching: 正♻️获取 - error: '坏🪨: {situation}' + error: '坏💩: {situation}' title: 体育查询 - class_info: 课❌信息 - test_score: 体🚻❌✈️ - total_score: 似年总分 + class_info: 课✖信息 + test_score: 体🚻❌🐔 + total_score: Ⅳ年总分 semester: '{gradeType} 第{gradeType}' subject: 🐘🤱🏻 - data: 📖🍊 + data: 📕🍊 score: 分📖 passed: ✈️格 score_string: '{score}分' toolbox: - title: ⑦他功能 + title: 🚴🏿他功能 payment: 🔈💴系统 - payment_description: 电💴该🦵🤣👨🏻 + payment_description: 电💴该🗣🤣Ⅷ repair: 🐒勤报修 repair_description: ⛔💊漏水断网 reserve: 🈳➖预约 reserve_description: 找个地◻️🐘牌 - mobile: ➖🕳🚪🐅 - mobile_description: 🌤⛽专用🚪🐅 + mobile: Ⅰ🕳🚪🐅 + mobile_description: 🌤🏠专用🚪🐅 network: 网络查询 - network_description: 希望永🚫🖐🏻💴 - physics: 🈚️理🐔🍋 + network_description: 希望永🚫📻💴 + physics: 🈚️理✈️🍋 physics_description: 希望🌿👈顺利 - discover: 睿④🔪航 - discover_description: 🖐🏻🏄‍⑦他功能 + discover: 睿似🔪航 + discover_description: 🚫🏄‍Ⅶ他功能 xdu_planet: all: 全⛔ - loading: ⛽♻️🀄️,🌤稍🛋️ <(=ω=)> - unknown_author: 未🧻👈者 - load_failed: 文章+♻️Ⅹ败,🧴👉需💊可➖点🐔🈶👆◻️🉐按🐂♻️⑥览🚴🏿里🐘🔓。 + loading: 🏠♻️🀄️,🌤稍🟰 <(=ω=)> + unknown_author: 未☞👈者 + load_failed: 文章➕♻️💩败,🧴🈶需💊可Ⅰ点✈️👉👆◻️🉐按🐂♻️⑥览⑦里🐘🔓。 no_comment: 暂🈚️评论 - reply_audit: '🩶复评论 #{reply_to} Ⅰ被🍊报或删➗️' + reply_audit: '🩶复评论 #{reply_to} Ⅰ被🍊报或删÷' reply: '🩶复评论 #{content}:{content}' have_been_audit: 📖评论🥻🚨被🍊报 audit: 🍊报 confirm_audit_dialog: - title: 确认💩否🍊报 - content: 📐ⅣⅡ🐒行,确定您🐘🍊报🤱🏻❓🍊报🐒该评论🩶👉⌚签,🚫➖定🩶删➗️。 + title: 确认Ⅹ否🍊报 + content: 🌂似Ⅱ🐒行,确定您🐘🍊报🤱🏻❓🍊报🐒该评论🩶👉⌚签,🖐🏻🥻定🩶删÷。 ongoing: 正♻️🍊报评论 failed: 🍊报🪨败 success: 🍊报×功 comment: 🩶复 - comment_success: 评论❌功 - comment_failed: 评论Ⅹ败,🌤去网络查👀🚴🏿⚛️日📃查👀Ⅶ查👀报错 + comment_success: 评论✖功 + comment_failed: 评论🪨败,🌤去网络查👀Ⅶ⚛️日☞查👀Ⅶ查👀报错 comment_canceled: 没🐘好💊🗣啥🤱🏻 - comment_loading: ➕♻️评论🀄️…… + comment_loading: 🏠♻️评论🀄️…… diff --git a/assets/flutter_i18n/zh_TW.yaml b/assets/flutter_i18n/zh_TW.yaml index 40c5e711..06ecb1b0 100644 --- a/assets/flutter_i18n/zh_TW.yaml +++ b/assets/flutter_i18n/zh_TW.yaml @@ -2,7 +2,7 @@ drag_text: 上拉請求更多 ready_text: 正在載入...... processing_text: 正在載入...... processed_text: 請求成功 -noMore_text: 資料沒有更多 +no_more_text: 資料沒有更多 failed_text: 資料獲取失敗更多 choose_semester: 選擇學期 error_detected: Ouch! 發生錯誤啦 @@ -11,7 +11,7 @@ confirm_title: 確認對話方塊 cancel: 取消 confirm: 確定 network_error: 網路錯誤,可能是沒聯網,可能是學校伺服器出現了故障:-P -error_detect: '遇到錯誤: {e}' +error_detect: "遇到錯誤: {e}" query_failed: 查詢失敗 not_school_network: 沒有在校園網環境 experiment_controller: @@ -31,30 +31,8 @@ login_process: slider: 滑塊驗證 after_process: 登入後處理 failed: 登入失敗,響應狀態碼:{statusCode} -catcher: - error_detected: 發生錯誤 - error_description: 詳情如下 -login: - identity_number: 學號 - password: 一站式登入密碼 - login: 登入 - incorrect_password_pattern: 使用者名稱或密碼不符合要求,學號必須 11 位且密碼非空 - on_login_progress: 正在登入學校一站式 - complete_login: 登入成功 - failed_login_cannot_connect_to_server: 無法連線到伺服器 - failed_login_with_code: 請求失敗,響應狀態碼:{code} - failed_login_with_message: 請求失敗,報錯資訊:{message} - failed_login_other: 未知錯誤,請聯絡開發者 - bottom_buttons: - clear_cache: 清除登入快取 - complete_clear_cache: 清理快取成功 - see_inspector: 檢視網路互動 - captcha_window: - title: 請輸入驗證碼 - hint: 輸入驗證碼 - message_on_empty: 請輸入驗證碼 - slider: - title: 伺服器認證服務 +catcher_detected: 發生錯誤 +catcher_description: 詳情如下 classtable: weekday: monday: 週一 @@ -103,24 +81,27 @@ classtable: 5: 五 6: 六 7: 日 - change_class_message: 調課資訊,從第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}節 + change_class_message: + 調課資訊,從第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}節 調整為第{newAffectedWeeksListStr}周星期{weekChar_newWeek}的 {newClassRangeStart}-{newClassRangeStop}節,{newClassroom}教室上課 - patch_class_message: 補課資訊,從第{newAffectedWeeksListStr}周 星期{weekChar_newWeek}的{newClassRangeStart}-{newClassRangeStop}節, + patch_class_message: + 補課資訊,從第{newAffectedWeeksListStr}周 星期{weekChar_newWeek}的{newClassRangeStart}-{newClassRangeStop}節, {newClassroom}補課 - stop_class_message: 停課資訊,第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}節 + stop_class_message: + 停課資訊,第{originalAffectedWeeks}周 星期{weekChar_originalWeek}的{originalClassRangeStart}-{originalClassRangeEnd}節 {originalClassroom}停課 - class_info: '編號: {classCode} | {classNumber} 班 + class_info: "編號: {classCode} | {classNumber} 班 安排變更:{classChange} - {teacherChange}' + {teacherChange}" not_arranged_page: title: 沒有時間安排的科目 empty_message: 目前全部課程均有時間安排 - content: '編號: {classCode} | {classNumber} 班 + content: "編號: {classCode} | {classNumber} 班 - 老師: {teacher}' - empty_class_message: '{semester_code} 學期沒有課程' + 老師: {teacher}" + empty_class_message: "{semester_code} 學期沒有課程" week_title: 第{week}周 noon_break: 午休 supper_break: 晚休 @@ -144,10 +125,10 @@ classtable: input_end_time_hint: 下課時間段 wheel_choose_hint: 第 {index} 節 course_detail_card: - class_number_string: '{number} 班' + class_number_string: "{number} 班" unknown_teacher: 老師未定 unknown_place: 地點未定 - class_period: '{start}-{stop}節' + class_period: "{start}-{stop}節" edit: 編輯 delete: 刪除 delete_title: 是否刪除課程資訊? @@ -158,16 +139,15 @@ creative_job: position_type: 職位型別 no_result: 沒有搜尋到結果 please_search: 請在上面搜尋框搜尋 - query_for_person: '招募 {exceptNumber} 人 · ' - end_time: 截止日期 {end_time} + query_for_person: "招募 {exceptNumber} 人 · " + end_time: 截止日期 {endTime} complete_choosing: 選擇完畢 - creative_job_description: - title: 工作詳情 - browser_hint: '*如果使用者感興趣,請按右上角的按鈕在瀏覽器中開啟*' - job_description_title: 崗位描述 - reward_title: 工作回報 - progress_title: 專案進度 - no_description: 沒有描述 + job_description: 工作詳情 + browser_hint: 如果使用者感興趣,請按右上角的按鈕在瀏覽器中開啟 + job_description_title: 崗位描述 + reward_title: 工作回報 + progress_title: 專案進度 + no_description: 沒有描述 empty_classroom: title: 空閒教室 date: 日期 {date} @@ -186,7 +166,7 @@ exam: no_arrangement: title: 目前無安排考試的科目 all_arranged: 目前所有科目均已安排考試 - subtitle: '編號: {id}' + subtitle: "編號: {id}" experiment: title: 物理實驗 ongoing: 正在進行實驗 @@ -207,10 +187,10 @@ homepage: loading: 正在載入 load_error: 載入錯誤 on_holiday: 假期中 - on_weekday: 第 ${c.getCurrentWeek(updateTime) + 1} 周 + on_weekday: 第 ${current} 周 loading_message: 請稍候,正在重新整理資訊 homepage: 主頁 - xdu_planet: 部落格星球 + planet: 部落格星球 setting: 設定 input_partner_data: route_not_exist: 匯入路徑不存在:P @@ -218,21 +198,17 @@ homepage: failed_import: 好像匯入檔案有點問題:P success_message: 匯入成功,如果打開了課表頁面請重新開啟 not_loaded: 還沒載入課程表,等會再來吧…… - confirm_dialog: - title: 確認對話方塊 - content: 目前有搭子課表資料,是否要覆蓋? + confirm_content: 目前有搭子課表資料,是否要覆蓋? login_message: 登入中,暫時顯示快取資料 successful_login_message: 登入成功 - password_wrong_dialog: - title: 使用者名稱或密碼有誤 - content: 是否重啟應用後手動登入? - confirm: 確認 - denial: 否,進入離線模式 - offline_mode_dialog: - title: 統一認證服務離線模式開啟 - content: 無法連線到統一認證服務伺服器,所有和其相關的服務暫時不可用。 成績查詢,考試資訊查詢,欠費查詢,校園卡查詢關閉。課表顯示快取資料。其他功能暫不受影響。 - 如有不便,敬請諒解。 - message: 離線模式下,一站式相關功能全部禁止使用 + password_wrong_title: 使用者名稱或密碼有誤 + password_wrong_content: 是否重啟應用後手動登入? + password_wrong_denial: 否,進入離線模式 + offline_mode_title: 統一認證服務離線模式開啟 + offline_mode_content: + 無法連線到統一認證服務伺服器,所有和其相關的服務暫時不可用。 成績查詢,考試資訊查詢,欠費查詢,校園卡查詢關閉。課表顯示快取資料。其他功能暫不受影響。 + 如有不便,敬請諒解。 + offline_mode: 離線模式下,一站式相關功能全部禁止使用 notice_card: empty_notice: 目前沒有獲取應用公告,請重新整理 no_notice_avaliable: 沒有獲取應用公告 @@ -251,29 +227,28 @@ homepage: no_arrangement_infoText: 暫無日程 electricity_card: title: 電量資訊 - current_electricity: '目前電量 ' - kwh: ' 度' - dialog: - title: 水電資訊 - content: 電費帳號:{account} 電量資訊:{electricityInfo.value} {electricityInfo} 欠費資訊:{owe_value} - 長按可以重新載入,有欠費一般代表水費 - confirm: 確定 + current_electricity: "目前電量 " + kwh: " 度" + dialog_title: 水電資訊 + dialog_content: + 電費帳號:{account} 電量資訊:{value} {electricityInfo} 欠費資訊:{owe_value} + 長按可以重新載入,有欠費一般代表水費 library_card: title: 圖書借閱 - current_borrow: '目前借書 ' - unit_of_book: ' 本' + current_borrow: "目前借書 " + unit_of_book: " 本" error_occured: 獲取借書資訊發生錯誤 fetching: 正在獲取借書資訊 no_return: 目前沒有待歸還書籍 - need_return: 待歸還{borrow_info.dued}本書籍 + need_return: 待歸還{dued}本書籍 no_info: 目前無法獲取資訊 fetching_info: 正在查詢資訊中 school_card_info_card: error_toast: 遇到錯誤,請聯絡開發者 fetching_toast: 正在獲取資訊,請稍後再來看 bill: 流水 - balance: '校園卡餘額 ' - unit: ' 元' + balance: "校園卡餘額 " + unit: " 元" error_occured: 獲取校園卡資訊發生錯誤 fetching: 正在獲取校園卡資訊 bottom_text_success: 查詢一卡通流水 @@ -294,33 +269,52 @@ library: title: 圖書館資訊 borrow_state_title: 借書狀態 search_book_title: 查詢藏書 - not_provided: 沒有相關資訊 - author: '作者 ' - publish_house: '出版社 ' - call_number: '索書號 ' - publish_date: '發行時間 ' + not_provided: 未提供相關資訊 + author: "作者 " + publish_house: "出版社 " + call_number: "索書號 " + publish_date: "發行時間 " isbn: ISBN - arrangement_code: '編排號碼 ' + arrangement_code: "編排號碼 " avaliable_borrow: 可借 storage: 館藏 on_shelve: 在架 book_code: 書籍編號:{barCode} - due_date: ' 到期' - borrow_str: ' 借閱' - after_due_date: ' 天前到期' - before_due_date: ' 天后' + due_date: " 到期" + borrow_str: " 借閱" + after_due_date: " 天前到期" + before_due_date: " 天后" can_be_renewable: 續借 cannot_be_renewable: 不可續借 renewing: 正在續借 - empty_borrow_list: '目前沒有查詢到在借圖書 + empty_borrow_list: "目前沒有查詢到在借圖書 - 不借書就要變成上面的小呆瓜咯' - borrow_list_info: 在借 {borrowListLength} 本,其中已過期 {duedLength} 本 + 不借書就要變成上面的小呆瓜咯" + borrow_list_info: 在借 {borrow} 本,其中已過期 {dued} 本 search_book_window: null search_here: 在此搜尋 book_detail: 書籍詳細資訊 no_result: 沒有結果 please_search: 請在上面搜尋框搜尋 +login: + identity_number: 學號 + password: 一站式登入密碼 + login: 登入 + incorrect_password_pattern: 使用者名稱或密碼不符合要求,學號必須 11 位且密碼非空 + on_login_progress: 正在登入學校一站式 + complete_login: 登入成功 + failed_login_cannot_connect_to_server: 無法連線到伺服器 + failed_login_with_code: 請求失敗,響應狀態碼:{code} + failed_login_with_message: 請求失敗,報錯資訊:{message} + failed_login_other: 未知錯誤,請聯絡開發者 + clear_cache: 清除登入快取 + complete_clear_cache: 清理快取成功 + see_inspector: 檢視網路互動 + captcha_window: + title: 請輸入驗證碼 + hint: 輸入驗證碼 + message_on_empty: 請輸入驗證碼 + slider_title: 伺服器認證服務 school_card_window: title: 校園卡流水資訊 income: 支出 {income} @@ -342,7 +336,8 @@ score: empty_list: 沒有選擇該學期的課程計入均分計算 sum_dialog: title: 小總結 - content: 所有科目的GPA:{gpa_all} 所有科目的均分:{avg_all} 所有科目的學分:{credit_all} 未透過科目:{unpassed} + content: + 所有科目的GPA:{gpa_all} 所有科目的均分:{avg_all} 所有科目的學分:{credit_all} 未透過科目:{unpassed} 公共選修課已經修得學分:{not_core_credit} 本程式提供的資料僅供參考,開發者對其準確性不負責 score_compose_card: no_detail: 未提供詳情資訊 @@ -353,7 +348,7 @@ score: score_info_card: title: 成績詳情 original_course: 初修 - failed: '[掛] ' + failed: "[掛] " credit: 學分 {credit} gpa: GPA {gpa} score: 成績 {score} @@ -375,7 +370,7 @@ setting: brightness_setting: 設定深淺色 simplify_timeline: 簡化日程時間軸 simplify_timeline_description: 沒有日程時 減少空間佔用 - account_setting: 介面設定 + account_setting: 賬號設定 sport_password_setting: 體育系統密碼設定 experiment_password_setting: 物理實驗系統密碼設定 electricity_password_setting: 電費帳號密碼設定 @@ -397,9 +392,9 @@ setting: title: 確認對話方塊 content: 是否要強制重新整理課表?同意後,將會從學校一站式後端重新獲取課表,耗時會比較久。 class_swift: 課程偏移設定 - class_swift_description: '正數錯後開學日期 負數提前開學日期 + class_swift_description: "正數錯後開學日期 負數提前開學日期 - 目前為 {swift}' + 目前為 {swift}" core_setting: 快取登入設定 check_catcher: 測試錯誤攔截器 check_logger: 檢視網路攔截器和日誌 @@ -416,7 +411,7 @@ setting: logging_out: 正在退出登入 need_close_dialog: title: 請關閉應用 - need_restart_d: 因為技術限制,使用者需要自行關閉視窗,然後重新開啟應用。 + content: 因為技術限制,使用者需要自行關閉視窗,然後重新開啟應用。 change_brightness_dialog: title: 顏色設定 follow_setting: 跟隨系統 @@ -425,8 +420,10 @@ setting: change_swift_dialog: title: 課程偏移設定 input_hint: 請在此輸入數字 + change_electricity_title: 修改電費帳號密碼 + change_experiment_title: 修改物理實驗賬號密碼 + change_sport_title: 修改體育系統賬號密碼 change_password_dialog: - title: 修改電費帳號密碼 input_hint: 請在此輸入密碼 blank_input: 輸入空白! easter_egg_page: @@ -442,21 +439,24 @@ setting: chitao1234: 開發:修復滑塊不對齊問題 dimole: 支援:輔助修復滑塊問題 elitewars: 設計:體育成績頁面 + godhu777777: 支援:繁體中文轉換程式碼和彩蛋程式碼 + hancl777: 支援:繁體中文轉換程式碼 hhzm: 支援:提供彩蛋程式碼 lsy223622: 設計:iOS 圖示 - nancuncloud: 開發:圖書館搜尋功能 + nancunchild: 開發:圖書館搜尋功能 pairman: 開發:成績快取功能和最佳化滑塊演算法 reverierxu: 設計:用於資訊展示的 ReX 卡片 - ray: 設計:開屏畫面 / 支援:iOS 開發 + ray: 設計:開屏畫面 / 支援:iOS 發行商 & 搭子課表 + shadowyingyi: 支援:兩次鴿子公眾號宣傳 stalomeow: 設計:首頁時間軸 / 開發:非同步登入 xeonds: 設計:設定頁面 / 開發:XDU Planet xiue233: 開發:Android 小部件和拼接 zcwzy: 開發:修復丁香電費 / 支援:研究生版本開發 homepage: 主頁 code: 開原始碼 - donate: 給我捐款 know_more: 知道更多 - copyright_notice: 本軟體複製基於 traintime_pda 程式碼(或稱 watermeter 程式碼)編譯, 程式碼按照 Mozilla + copyright_notice: + 本軟體複製基於 traintime_pda 程式碼(或稱 watermeter 程式碼)編譯, 程式碼按照 Mozilla Public License, v. 2.0 授權。 本程式和西安電子科技大學,體適能服務,書蝸,電錶等服務無關。 Copyright 2023-Present BenderBlog Rodriguez and contributors. The Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed @@ -466,17 +466,17 @@ setting: title: 關於本軟體 sport: fetching: 正在獲取 - error: '壞事: {situation}' + error: "壞事: {situation}" title: 體育查詢 class_info: 課程資訊 test_score: 體測成績 total_score: 四年總分 - semester: '{year} 第{gradeType}' + semester: "{year} 第{gradeType}" subject: 專案 data: 資料 score: 分數 passed: 及格 - score_string: '{score}分' + score_string: "{score}分" toolbox: title: 其他功能 payment: 繳費系統 @@ -499,8 +499,8 @@ xdu_planet: unknown_author: 未知作者 load_failed: 文章載入失敗,如有需要可以點選右上方的按鈕在瀏覽器裡開啟。 no_comment: 暫無評論 - reply_audit: '回覆評論 #{reply_to} 已被舉報或刪除' - reply: '回覆評論 #{reply_to}:{content}' + reply_audit: "回覆評論 #{reply_to} 已被舉報或刪除" + reply: "回覆評論 #{reply_to}:{content}" have_been_audit: 本評論已經被舉報 audit: 舉報 confirm_audit_dialog: diff --git a/lib/main.dart b/lib/main.dart index e3df44b1..8185ca51 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -109,6 +109,7 @@ class _MyAppState extends State { translationLoader: FileTranslationLoader( fallbackFile: "zh_CN", useCountryCode: true, + forcedLocale: const Locale('zh_CN'), ), missingTranslationHandler: (key, locale) { log.info( @@ -122,7 +123,9 @@ class _MyAppState extends State { GlobalCupertinoLocalizations.delegate, ], supportedLocales: const [ + Locale('zh', 'TW'), Locale('zh', 'CN'), + Locale('zh', 'SG'), // CFBB Lang Alternative ], debugShowCheckedModeBanner: false, scrollBehavior: MyCustomScrollBehavior(), diff --git a/lib/model/toolbox_addresses.dart b/lib/model/toolbox_addresses.dart index e4b15460..92af34f5 100644 --- a/lib/model/toolbox_addresses.dart +++ b/lib/model/toolbox_addresses.dart @@ -1,58 +1,8 @@ // Copyright 2023 BenderBlog Rodriguez and contributors. // SPDX-License-Identifier: MPL-2.0 +import 'package:flutter/widgets.dart'; -import 'package:flutter/material.dart'; -import 'package:ming_cute_icons/ming_cute_icons.dart'; - -enum WebViewAddresses { - payment( - name: "缴费系统", - url: "https://payment.xidian.edu.cn/MNetWorkUI/showPublic", - description: "电费该交了吧", - iconData: MingCuteIcons.mgc_exchange_cny_line, - ), - repair( - name: "后勤报修", - url: "https://ids.xidian.edu.cn/authserver/login?service=" - "https%3A%2F%2Fids.xidian.edu.cn%2Fauthserver%2Foauth2.0%2F" - "callbackAuthorize%3Fclient_id%3D869608421533880320%26" - "redirect_uri%3Dhttp%253A%252F%252Frepair.xidian.edu.cn%252F" - "appsys%252FxidianCasLogin%252FoauthLogin%26response_type%3D" - "code%26state%3Dhome%26client_name%3DCasOAuthClient", - description: "不要漏水断网", - iconData: MingCuteIcons.mgc_tool_line, - ), - reserve( - name: "空间预约", - url: "http://libspace.xidian.edu.cn", - description: "找个地方打牌", - iconData: MingCuteIcons.mgc_building_4_line, - ), - mobileEntry( - name: "移动门户", - url: "https://xxcapp.xidian.edu.cn/site/xidianPage/home", - description: "请假专用门户", - iconData: MingCuteIcons.mgc_chat_2_line, - ), - network( - name: "网络查询", - url: "https://zfw.xidian.edu.cn", - description: "希望永不收费", - iconData: MingCuteIcons.mgc_wifi_line, - ), - calculator( - name: "物理计算", - url: "https://experiment-helper.wizzstudio.com/#/", - description: "希望操作顺利", - iconData: MingCuteIcons.mgc_counter_2_line, - ), - ruisiEntry( - name: "睿思导航", - url: "https://nav.xdruisi.com/", - description: "补充其他功能", - iconData: MingCuteIcons.mgc_web_line, - ); - +class WebViewAddresses { final String name; final String url; final String description; diff --git a/lib/page/creative_job/creative_job.dart b/lib/page/creative_job/creative_job.dart index 682fdee2..46a46bb3 100644 --- a/lib/page/creative_job/creative_job.dart +++ b/lib/page/creative_job/creative_job.dart @@ -1,6 +1,7 @@ // Copyright 2023 BenderBlog Rodriguez and contributors. // SPDX-License-Identifier: MPL-2.0 +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/both_side_sheet.dart'; import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; @@ -115,7 +116,10 @@ class _CreativeJobViewState extends State { filled: true, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - hintText: "搜索需求", + hintText: FlutterI18n.translate( + context, + "creative_job.search_hint", + ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(100), borderSide: BorderSide.none, @@ -139,7 +143,10 @@ class _CreativeJobViewState extends State { child: CategoryChoiceView( data: searchTags ?? ("", []), ), - title: "选择种类", + title: FlutterI18n.translate( + context, + "creative_job.choice_type", + ), ); if (mounted) { setState(() { @@ -147,7 +154,10 @@ class _CreativeJobViewState extends State { }); } }, - child: const Text("职位类型"), + child: Text(FlutterI18n.translate( + context, + "creative_job.position_type", + )), ), ), ], @@ -155,12 +165,30 @@ class _CreativeJobViewState extends State { ), body: EasyRefresh( footer: ClassicFooter( - dragText: '上拉请求更多'.tr, - readyText: '正在加载......'.tr, - processingText: '正在加载......'.tr, - processedText: '请求成功'.tr, - noMoreText: '数据没有更多'.tr, - failedText: '数据获取失败更多'.tr, + dragText: FlutterI18n.translate( + context, + "drag_text", + ), + readyText: FlutterI18n.translate( + context, + "ready_text", + ), + processingText: FlutterI18n.translate( + context, + "processing_text", + ), + processedText: FlutterI18n.translate( + context, + "processed_text", + ), + noMoreText: FlutterI18n.translate( + context, + "no_more_text", + ), + failedText: FlutterI18n.translate( + context, + "failed_text", + ), infiniteOffset: null, ), onLoad: () async { @@ -178,16 +206,23 @@ class _CreativeJobViewState extends State { : isSearching.value ? const Center(child: CircularProgressIndicator()) : jobs.isNotEmpty - ? const EmptyListView(text: "没有搜索到结果") - : const Column( + ? EmptyListView( + text: FlutterI18n.translate( + context, + "creative_job.no_result", + )) + : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( + const Icon( Icons.search, size: 96, ), - Divider(color: Colors.transparent), - Text("请在上面搜索框搜索"), + const Divider(color: Colors.transparent), + Text(FlutterI18n.translate( + context, + "creative_job.please_search", + )), ], ), ), @@ -235,15 +270,25 @@ class CreativeJobListTile extends StatelessWidget { Wrap( spacing: 4.0, children: [ - Text( - "招募 ${job.exceptNumber} 人 · ", - ), + Text(FlutterI18n.translate( + context, + "creative_job.query_for_person", + translationParams: { + "exceptNumber": job.exceptNumber.toString(), + }, + )), Text( "${job.project.name} · ", ), - Text( - "截止日期 ${Jiffy.parseFromDateTime(job.endTime).format(pattern: "yyyy 年 MM 月 dd 日")}", - ), + Text(FlutterI18n.translate( + context, + "creative_job.end_time", + translationParams: { + /// TODO: change it to locale... + "endTime": Jiffy.parseFromDateTime(job.endTime) + .format(pattern: "yyyy 年 MM 月 dd 日"), + }, + )), ], ), ], diff --git a/lib/page/creative_job/creative_job_choice.dart b/lib/page/creative_job/creative_job_choice.dart index 355cb09c..af98d2fd 100644 --- a/lib/page/creative_job/creative_job_choice.dart +++ b/lib/page/creative_job/creative_job_choice.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/model/xidian_ids/creative.dart'; class CategoryChoiceView extends StatefulWidget { @@ -34,7 +35,10 @@ class _CategoryChoiceViewState extends State { onPressed: () { Navigator.pop(context, (categoryChoiced, subTags)); }, - child: const Text("选择完毕"), + child: Text(FlutterI18n.translate( + context, + "creative_job.complete_choosing", + )), ), ...List.generate( skill.keys.toList().length, diff --git a/lib/page/creative_job/creative_job_description.dart b/lib/page/creative_job/creative_job_description.dart index d3abe4d3..d9b3bb2e 100644 --- a/lib/page/creative_job/creative_job_description.dart +++ b/lib/page/creative_job/creative_job_description.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:jiffy/jiffy.dart'; import 'package:watermeter/model/xidian_ids/creative.dart'; import 'package:watermeter/page/public_widget/public_widget.dart'; @@ -20,7 +21,10 @@ class CreativeJobDescription extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text("工作详情"), + title: Text(FlutterI18n.translate( + context, + "creative_job.job_description", + )), actions: [ IconButton( onPressed: () => @@ -70,23 +74,28 @@ class CreativeJobDescription extends StatelessWidget { const SizedBox(height: 8), MarkdownBody(data: ''' -招募 ${job.exceptNumber} 人 · ${job.project.name} +${FlutterI18n.translate(context, "creative_job.query_for_person", translationParams: { + "exceptNumber": job.exceptNumber.toString() + })}${job.project.name} -截止 ${Jiffy.parseFromDateTime(job.endTime).format(pattern: "yyyy 年 MM 月 dd 日")} +${FlutterI18n.translate(context, "creative_job.end_time", translationParams: { + "endTime": Jiffy.parseFromDateTime(job.endTime) + .format(pattern: "yyyy 年 MM 月 dd 日") + })} -*如果用户感兴趣,请按右上角的按钮在浏览器中打开* +*${FlutterI18n.translate(context, "creative_job.browser_hint")}* -## 岗位描述 +## ${FlutterI18n.translate(context, "creative_job.job_description_title")} -${job.description.isNotEmpty ? job.description : "没有描述"} +${job.description.isNotEmpty ? job.description : FlutterI18n.translate(context, "creative_job.no_description")}} -## 工作回报 +## ${FlutterI18n.translate(context, "creative_job.reward_title")} -${job.reward.isNotEmpty ? job.reward : "没有描述"} +${job.reward.isNotEmpty ? job.reward : FlutterI18n.translate(context, "creative_job.no_description")} -## 项目进度 +## ${FlutterI18n.translate(context, "creative_job.progress_title")} -${job.progress.isEmpty ? "没有描述" : job.progress} +${job.progress.isEmpty ? FlutterI18n.translate(context, "creative_job.no_description") : job.progress} '''), ], ), diff --git a/lib/page/empty_classroom/empty_classroom_search_window.dart b/lib/page/empty_classroom/empty_classroom_search_window.dart index 5c94a044..0237ee0d 100644 --- a/lib/page/empty_classroom/empty_classroom_search_window.dart +++ b/lib/page/empty_classroom/empty_classroom_search_window.dart @@ -4,6 +4,7 @@ import 'package:calendar_date_picker2/calendar_date_picker2.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:jiffy/jiffy.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/empty_classroom.dart'; @@ -138,9 +139,14 @@ class _EmptyClassroomSearchWindowState } }); }, - child: Text( - "日期 ${Jiffy.parseFromDateTime(time).format(pattern: "yyyy-MM-dd")}", - ), + child: Text(FlutterI18n.translate( + context, + "empty_classroom.date", + translationParams: { + "date": Jiffy.parseFromDateTime(time) + .format(pattern: "yyyy-MM-dd") + }, + )), ).padding(right: 8), TextButton( style: TextButton.styleFrom( @@ -152,9 +158,11 @@ class _EmptyClassroomSearchWindowState }); chooseBuilding(); }, - child: Text( - "教学楼 ${chosen.name}", - ), + child: Text(FlutterI18n.translate( + context, + "empty_classroom.building", + translationParams: {"building": chosen.name}, + )), ), TextField( controller: text, @@ -168,7 +176,10 @@ class _EmptyClassroomSearchWindowState horizontal: 16, vertical: 8, ), - hintText: "教室名称或者教室代码", + hintText: FlutterI18n.translate( + context, + "empty_classroom.search_hint", + ), hintStyle: const TextStyle(fontSize: 14), border: OutlineInputBorder( borderRadius: BorderRadius.circular(100), @@ -191,28 +202,35 @@ class _EmptyClassroomSearchWindowState DataTable2( columnSpacing: 0, horizontalMargin: 6, - columns: const [ + columns: [ DataColumn2( - label: Center(child: Text('教室')), + label: Center( + child: Text( + FlutterI18n.translate( + context, + "empty_classroom.classroom", + ), + ), + ), size: ColumnSize.L, ), - DataColumn2( + const DataColumn2( label: Center(child: Text('1-2')), size: ColumnSize.S, ), - DataColumn2( + const DataColumn2( label: Center(child: Text('3-4')), size: ColumnSize.S, ), - DataColumn2( + const DataColumn2( label: Center(child: Text('5-6')), size: ColumnSize.S, ), - DataColumn2( + const DataColumn2( label: Center(child: Text('7-8')), size: ColumnSize.S, ), - DataColumn2( + const DataColumn2( label: Center(child: Text('9-10')), size: ColumnSize.S, ), diff --git a/lib/page/empty_classroom/empty_classroom_window.dart b/lib/page/empty_classroom/empty_classroom_window.dart index 0d6a8d67..76df926d 100644 --- a/lib/page/empty_classroom/empty_classroom_window.dart +++ b/lib/page/empty_classroom/empty_classroom_window.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/empty_classroom.dart'; import 'package:watermeter/page/empty_classroom/empty_classroom_search_window.dart'; @@ -27,7 +28,14 @@ class _EmptyClassroomWindowState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("空闲教室")), + appBar: AppBar( + title: Text( + FlutterI18n.translate( + context, + "empty_classroom.title", + ), + ), + ), body: FutureBuilder( future: places, builder: (context, snapshot) { diff --git a/lib/page/exam/exam_info_window.dart b/lib/page/exam/exam_info_window.dart index fda7f4e2..86659234 100644 --- a/lib/page/exam/exam_info_window.dart +++ b/lib/page/exam/exam_info_window.dart @@ -3,6 +3,7 @@ // Exam Infomation Interface. +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -33,13 +34,19 @@ class _ExamInfoWindowState extends State { if (offline && c.status == ExamStatus.cache) { showToast( context: context, - msg: "已显示缓存考试安排信息", + msg: FlutterI18n.translate( + context, + "exam.cache_hint", + ), ); } return Scaffold( appBar: AppBar( - title: const Text("考试安排"), + title: Text(FlutterI18n.translate( + context, + "exam.title", + )), actions: [ IconButton( icon: const Icon(Icons.more_time), @@ -65,7 +72,12 @@ class _ExamInfoWindowState extends State { if (c.isDisQualified.isNotEmpty) ...[true, false], ], children: [ - const TimelineTitle(title: "未完成考试"), + TimelineTitle( + title: FlutterI18n.translate( + context, + "exam.not_finished", + ), + ), Builder(builder: (context) { final isNotFinished = c.isNotFinished(widget.time); if (isNotFinished.isNotEmpty) { @@ -74,17 +86,32 @@ class _ExamInfoWindowState extends State { .toList() .toColumn(); } else { - return const ExamInfoCard(title: "所有考试全部完成"); + return ExamInfoCard( + title: FlutterI18n.translate( + context, + "exam.all_finished", + ), + ); } }), if (c.isDisQualified.isNotEmpty) - const TimelineTitle(title: "无法完成考试"), + TimelineTitle( + title: FlutterI18n.translate( + context, + "exam.unable_to_exam", + ), + ), if (c.isDisQualified.isNotEmpty) c.isDisQualified .map((e) => ExamInfoCard(toUse: e)) .toList() .toColumn(), - const TimelineTitle(title: "已完成考试"), + TimelineTitle( + title: FlutterI18n.translate( + context, + "exam.finished", + ), + ), Builder(builder: (context) { final isFinished = c.isFinished(widget.time); if (isFinished.isNotEmpty) { @@ -93,13 +120,23 @@ class _ExamInfoWindowState extends State { .toList() .toColumn(); } else { - return const ExamInfoCard(title: "一门还没考呢"); + return ExamInfoCard( + title: FlutterI18n.translate( + context, + "exam.none_finished", + ), + ); } }), ], ).safeArea(); } else { - return const EmptyListView(text: "目前没有考试安排"); + return EmptyListView( + text: FlutterI18n.translate( + context, + "exam.no_exam_arrangement", + ), + ); } } else if (c.status == ExamStatus.error) { return Center(child: Text(c.error.toString())); diff --git a/lib/page/exam/not_arranged_info.dart b/lib/page/exam/not_arranged_info.dart index 8fbb683f..3b33f41a 100644 --- a/lib/page/exam/not_arranged_info.dart +++ b/lib/page/exam/not_arranged_info.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/model/xidian_ids/exam.dart'; import 'package:watermeter/page/public_widget/empty_list_view.dart'; import 'package:watermeter/page/public_widget/public_widget.dart'; @@ -14,11 +15,21 @@ class NoArrangedInfo extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text("目前无安排考试的科目"), + title: Text( + FlutterI18n.translate( + context, + "exam.no_arrangement.title", + ), + ), ), body: Builder(builder: (context) { if (list.isEmpty) { - return const EmptyListView(text: "目前所有科目均已安排考试"); + return EmptyListView( + text: FlutterI18n.translate( + context, + "exam.no_arrangement.all_arranged", + ), + ); } return DataList( list: list, @@ -37,7 +48,13 @@ class NoArrangedInfo extends StatelessWidget { color: Theme.of(context).colorScheme.primary, ), ), - subtitle: Text("编号: ${toUse.id}"), + subtitle: Text( + FlutterI18n.translate( + context, + "exam.no_arrangement.subtitle", + translationParams: {"id": toUse.id}, + ), + ), ), ), ); diff --git a/lib/page/experiment/experiment_info_card.dart b/lib/page/experiment/experiment_info_card.dart index 269bcaea..21c07c1f 100644 --- a/lib/page/experiment/experiment_info_card.dart +++ b/lib/page/experiment/experiment_info_card.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/model/xidian_ids/experiment.dart'; import 'package:watermeter/page/public_widget/public_widget.dart'; import 'package:watermeter/page/public_widget/re_x_card.dart'; @@ -51,8 +52,12 @@ class ExperimentInfoCard extends StatelessWidget { flex: 1, child: InformationWithIcon( icon: Icons.book, - text: - data!.reference.isNotEmpty ? data!.reference : "未提供", + text: data!.reference.isNotEmpty + ? data!.reference + : FlutterI18n.translate( + context, + "experiment.not_provided", + ), ), ), ], diff --git a/lib/page/experiment/experiment_window.dart b/lib/page/experiment/experiment_window.dart index 27d8420b..40bbd9f9 100644 --- a/lib/page/experiment/experiment_window.dart +++ b/lib/page/experiment/experiment_window.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/controller/experiment_controller.dart'; @@ -23,7 +24,14 @@ class _ExperimentWindowState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("物理实验")), + appBar: AppBar( + title: Text( + FlutterI18n.translate( + context, + "experiment.title", + ), + ), + ), body: GetBuilder( builder: (controller) { if (controller.status == ExperimentStatus.fetched || @@ -45,7 +53,12 @@ class _ExperimentWindowState extends State { ], children: [ if (doing.isNotEmpty) ...[ - const TimelineTitle(title: "正在进行实验"), + TimelineTitle( + title: FlutterI18n.translate( + context, + "experiment.ongoing", + ), + ), Column( children: List.generate( doing.length, @@ -55,7 +68,12 @@ class _ExperimentWindowState extends State { ), ), ], - const TimelineTitle(title: "未完成实验"), + TimelineTitle( + title: FlutterI18n.translate( + context, + "experiment.not_finished", + ), + ), unDone.isNotEmpty ? Column( children: List.generate( @@ -65,12 +83,26 @@ class _ExperimentWindowState extends State { ), ), ) - : const TimelineTitle( - title: "所有实验全部完成", + : TimelineTitle( + title: FlutterI18n.translate( + context, + "experiment.all_finished", + ), ), - const TimelineTitle(title: "已完成实验"), + TimelineTitle( + title: FlutterI18n.translate( + context, + "experiment.finished", + ), + ), ExperimentInfoCard( - title: "目前分数总和:${controller.sum}", + title: FlutterI18n.translate( + context, + "experiment.score_sum", + translationParams: { + "sum": controller.sum.toString(), + }, + ), ), done.isNotEmpty ? Column( @@ -81,8 +113,11 @@ class _ExperimentWindowState extends State { ), ), ) - : const TimelineTitle( - title: "目前没有已经完成的实验", + : TimelineTitle( + title: FlutterI18n.translate( + context, + "experiment.none_finished", + ), ), ], ).safeArea(); diff --git a/lib/page/homepage/toolbox/creative_card.dart b/lib/page/homepage/toolbox/creative_card.dart index 9b8d4bca..cfe0dd81 100644 --- a/lib/page/homepage/toolbox/creative_card.dart +++ b/lib/page/homepage/toolbox/creative_card.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:ming_cute_icons/ming_cute_icons.dart'; import 'package:watermeter/page/creative_job/creative_job.dart'; @@ -17,7 +18,13 @@ class CreativeCard extends StatelessWidget { return SmallFunctionCard( onTap: () async { if (offline) { - showToast(context: context, msg: "脱机模式下,一站式相关功能全部禁止使用"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "homepage.offline_mode", + ), + ); } else { context.pushReplacement(const CreativeJobView()); } diff --git a/lib/page/homepage/toolbox/empty_classroom_card.dart b/lib/page/homepage/toolbox/empty_classroom_card.dart index f025171c..accb58a6 100644 --- a/lib/page/homepage/toolbox/empty_classroom_card.dart +++ b/lib/page/homepage/toolbox/empty_classroom_card.dart @@ -1,6 +1,7 @@ // Copyright 2023 BenderBlog Rodriguez and contributors. // SPDX-License-Identifier: MPL-2.0 +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; @@ -20,7 +21,13 @@ class EmptyClassroomCard extends StatelessWidget { builder: (c) => SmallFunctionCard( onTap: () async { if (offline) { - showToast(context: context, msg: "脱机模式下,一站式相关功能全部禁止使用"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "homepage.offline_mode", + ), + ); } else { context.pushReplacement(const EmptyClassroomWindow()); } diff --git a/lib/page/homepage/toolbox/exam_card.dart b/lib/page/homepage/toolbox/exam_card.dart index c1df312f..3f4aa5b4 100644 --- a/lib/page/homepage/toolbox/exam_card.dart +++ b/lib/page/homepage/toolbox/exam_card.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:get/get.dart'; import 'package:ming_cute_icons/ming_cute_icons.dart'; @@ -25,9 +26,21 @@ class ExamCard extends StatelessWidget { if (c.status == ExamStatus.cache || c.status == ExamStatus.fetched) { context.pushReplacement(ExamInfoWindow(time: updateTime)); } else if (c.status != ExamStatus.error) { - showToast(context: context, msg: "请稍候,正在获取考试信息"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "homepage.toolbox.exam_fetching", + ), + ); } else if (offline) { - showToast(context: context, msg: "脱机模式下,一站式相关功能全部禁止使用"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "homepage.offline_mode", + ), + ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( @@ -37,7 +50,13 @@ class ExamCard extends StatelessWidget { )), ), ); - showToast(context: context, msg: "遇到错误,请联系开发者"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "homepage.toolbox.exam_error", + ), + ); } }, icon: MingCuteIcons.mgc_calendar_line, diff --git a/lib/page/homepage/toolbox/score_card.dart b/lib/page/homepage/toolbox/score_card.dart index 528b7084..81c97068 100644 --- a/lib/page/homepage/toolbox/score_card.dart +++ b/lib/page/homepage/toolbox/score_card.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:watermeter/page/public_widget/context_extension.dart'; import 'package:watermeter/page/score/score.dart'; @@ -17,7 +18,13 @@ class ScoreCard extends StatelessWidget { return SmallFunctionCard( onTap: () { if (offline && !ScoreSession.isCacheExist) { - showToast(context: context, msg: "脱机状态且无缓存成绩数据,无法访问"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "homepage.toolbox.score_cannot_reach", + ), + ); } else { context.pushReplacement(const ScoreWindow()); } diff --git a/lib/page/library/book_detail_card.dart b/lib/page/library/book_detail_card.dart index 4a9138ea..ea52fc25 100644 --- a/lib/page/library/book_detail_card.dart +++ b/lib/page/library/book_detail_card.dart @@ -4,6 +4,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/library.dart'; import 'package:watermeter/page/library/book_place_card.dart'; @@ -79,16 +80,23 @@ class _BookDetailCardState extends State { const SizedBox(height: 8), Text.rich( TextSpan(children: [ - const TextSpan( - text: "作者 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.author", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), ), ), TextSpan( - text: widget.toUse.author ?? "没有提供", + text: widget.toUse.author ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -97,16 +105,23 @@ class _BookDetailCardState extends State { ]), ), Text.rich(TextSpan(children: [ - const TextSpan( - text: "出版社 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.publish_house", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), ), ), TextSpan( - text: widget.toUse.publisherHouse ?? "没有相关信息", + text: widget.toUse.publisherHouse ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -114,9 +129,12 @@ class _BookDetailCardState extends State { ), ])), Text.rich(TextSpan(children: [ - const TextSpan( - text: "索书号 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.call_number", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), @@ -131,16 +149,23 @@ class _BookDetailCardState extends State { ), ])), Text.rich(TextSpan(children: [ - const TextSpan( - text: "发行时间 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.publish_date", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), ), ), TextSpan( - text: widget.toUse.publishYear ?? "没有相关信息", + text: widget.toUse.publishYear ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -148,16 +173,23 @@ class _BookDetailCardState extends State { ), ])), Text.rich(TextSpan(children: [ - const TextSpan( - text: "ISBN ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.isbn", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), ), ), TextSpan( - text: widget.toUse.isbn ?? "没有提供", + text: widget.toUse.isbn ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -165,9 +197,12 @@ class _BookDetailCardState extends State { ), ])), Text.rich(TextSpan(children: [ - const TextSpan( - text: "编排号码 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.arrangement_code", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), diff --git a/lib/page/library/book_info_card.dart b/lib/page/library/book_info_card.dart index 1b5839c8..6fe5b0b1 100644 --- a/lib/page/library/book_info_card.dart +++ b/lib/page/library/book_info_card.dart @@ -6,6 +6,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/library.dart'; import 'package:watermeter/repository/logger.dart'; @@ -62,16 +63,23 @@ class BookInfoCard extends StatelessWidget { const SizedBox(height: 2), Text.rich( TextSpan(children: [ - const TextSpan( - text: "作者 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.author", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), ), ), TextSpan( - text: toUse.author ?? "没有提供", + text: toUse.author ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -82,16 +90,23 @@ class BookInfoCard extends StatelessWidget { overflow: TextOverflow.ellipsis, ), Text.rich(TextSpan(children: [ - const TextSpan( - text: "出版社 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.publish_house", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), ), ), TextSpan( - text: toUse.publisherHouse ?? "没有相关信息", + text: toUse.publisherHouse ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -99,9 +114,12 @@ class BookInfoCard extends StatelessWidget { ), ])), Text.rich(TextSpan(children: [ - const TextSpan( - text: "索书号 ", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.call_number", + ), + style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), @@ -128,9 +146,12 @@ class BookInfoCard extends StatelessWidget { fontWeight: FontWeight.w600, ), ), - const TextSpan( - text: "可借", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.avaliable_borrow", + ), + style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), @@ -155,9 +176,12 @@ class BookInfoCard extends StatelessWidget { fontWeight: FontWeight.w600, ), ), - const TextSpan( - text: "馆藏", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.storage", + ), + style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFFBFBFBF), @@ -179,11 +203,4 @@ class BookInfoCard extends StatelessWidget { .clipRRect(all: 16) .padding(all: 4); } - - String validateList(List? inputList) { - if (inputList == null || inputList.isEmpty) { - return "没有相关信息"; - } - return inputList.first; - } } diff --git a/lib/page/library/book_place_card.dart b/lib/page/library/book_place_card.dart index efe12db9..92790e65 100644 --- a/lib/page/library/book_place_card.dart +++ b/lib/page/library/book_place_card.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:ming_cute_icons/ming_cute_icons.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/model/xidian_ids/library.dart'; @@ -29,7 +30,11 @@ class BookPlaceCard extends StatelessWidget { ), const SizedBox(width: 8), Text( - toUse.locationName ?? "没有位置信息", + toUse.locationName ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), style: TextStyle( fontWeight: FontWeight.w400, fontSize: 16, @@ -41,7 +46,17 @@ class BookPlaceCard extends StatelessWidget { ].toRow(), const SizedBox(height: 8), Text( - "书籍编号:${toUse.barCode}", + FlutterI18n.translate( + context, + "library.book_code", + translationParams: { + "barCode": toUse.barCode ?? + FlutterI18n.translate( + context, + "library.not_provided", + ), + }, + ), style: TextStyle( fontWeight: FontWeight.w400, color: toUse.processType == "在架" diff --git a/lib/page/library/borrow_info_card.dart b/lib/page/library/borrow_info_card.dart index ef763fa6..3c2ff7d7 100644 --- a/lib/page/library/borrow_info_card.dart +++ b/lib/page/library/borrow_info_card.dart @@ -6,6 +6,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:sn_progress_dialog/progress_dialog.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -82,9 +83,12 @@ class BorrowInfoCard extends StatelessWidget { ), ) ]), - const TextSpan( - text: " 借阅", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.borrow_str", + ), + style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Colors.blueGrey, @@ -120,9 +124,12 @@ class BorrowInfoCard extends StatelessWidget { fontWeight: FontWeight.w600, ), ), - const TextSpan( - text: " 到期", - style: TextStyle( + TextSpan( + text: FlutterI18n.translate( + context, + "library.due_date", + ), + style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Colors.blueGrey, @@ -150,7 +157,15 @@ class BorrowInfoCard extends StatelessWidget { ), ), TextSpan( - text: isOverdue ? " 天前到期" : " 天后", + text: isOverdue + ? FlutterI18n.translate( + context, + "library.after_due_date", + ) + : FlutterI18n.translate( + context, + "library.before_due_date", + ), style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w600, @@ -159,7 +174,15 @@ class BorrowInfoCard extends StatelessWidget { ), ])); final button = Text( - isOverdue ? "不可续借" : "续借", + isOverdue + ? FlutterI18n.translate( + context, + "library.cannot_be_renewable", + ) + : FlutterI18n.translate( + context, + "library.can_be_renewable", + ), style: TextStyle( color: Theme.of(context).colorScheme.onPrimary, fontWeight: FontWeight.w600, @@ -174,7 +197,12 @@ class BorrowInfoCard extends StatelessWidget { onTap: () { if (!isOverdue) { ProgressDialog pd = ProgressDialog(context: context); - pd.show(msg: "正在续借"); + pd.show( + msg: FlutterI18n.translate( + context, + "library.renewing", + ), + ); LibrarySession().renew(toUse.loanId).then((value) { if (context.mounted) { pd.close(); diff --git a/lib/page/library/borrow_list_window.dart b/lib/page/library/borrow_list_window.dart index feb51fa7..be16b3dc 100644 --- a/lib/page/library/borrow_list_window.dart +++ b/lib/page/library/borrow_list_window.dart @@ -3,6 +3,7 @@ // Borrow list, shows the user's borrowlist. +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -72,7 +73,12 @@ class BorrowListDetail extends StatelessWidget { ), ); } else { - return const EmptyListView(text: "目前没有查询到在借图书\n不借书就要变成上面的小呆瓜咯"); + return EmptyListView( + text: FlutterI18n.translate( + context, + "library.empty_borrow_list", + ), + ); } }), bottomNavigationBar: BottomAppBar( @@ -80,8 +86,12 @@ class BorrowListDetail extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "在借 ${borrow_info.borrowList.length} 本,其中已过期 ${borrow_info.dued} 本", + I18nText( + "library.borrow_list_info", + translationParams: { + "borrow": borrow_info.borrowList.length.toString(), + "dued": borrow_info.dued.toString(), + }, ), ], ), diff --git a/lib/page/library/library_window.dart b/lib/page/library/library_window.dart index 2867b155..67d4fb56 100644 --- a/lib/page/library/library_window.dart +++ b/lib/page/library/library_window.dart @@ -3,6 +3,7 @@ // Library Window. import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/library/borrow_list_window.dart'; import 'package:watermeter/page/library/search_book_window.dart'; @@ -15,14 +16,20 @@ class LibraryWindow extends StatelessWidget { length: 2, child: Scaffold( appBar: AppBar( - title: const Text("图书馆信息"), - bottom: const TabBar( + title: Text(FlutterI18n.translate(context, "library.title")), + bottom: TabBar( tabs: [ Tab( - text: "借书状态", + text: FlutterI18n.translate( + context, + "library.borrow_state_title", + ), ), Tab( - text: "查询藏书", + text: FlutterI18n.translate( + context, + "library.search_book_title", + ), ), ], ), diff --git a/lib/page/library/search_book_window.dart b/lib/page/library/search_book_window.dart index c1a4729b..acbc6960 100644 --- a/lib/page/library/search_book_window.dart +++ b/lib/page/library/search_book_window.dart @@ -1,6 +1,7 @@ // Copyright 2023 BenderBlog Rodriguez and contributors. // SPDX-License-Identifier: MPL-2.0 +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/both_side_sheet.dart'; import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; @@ -80,14 +81,17 @@ class _SearchBookWindowState extends State constraints: const BoxConstraints(maxWidth: 480), child: TextFormField( controller: text, - decoration: const InputDecoration( + decoration: InputDecoration( filled: true, fillColor: Colors.transparent, - hintText: "在此搜索", + hintText: FlutterI18n.translate( + context, + "library.search_here", + ), isDense: false, - contentPadding: EdgeInsets.symmetric(vertical: 8.0), - prefixIcon: Icon(Icons.search), - border: OutlineInputBorder( + contentPadding: const EdgeInsets.symmetric(vertical: 8.0), + prefixIcon: const Icon(Icons.search), + border: const OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10)), ), ), @@ -105,12 +109,30 @@ class _SearchBookWindowState extends State ), EasyRefresh( footer: ClassicFooter( - dragText: '上拉请求更多'.tr, - readyText: '正在加载......'.tr, - processingText: '正在加载......'.tr, - processedText: '请求成功'.tr, - noMoreText: '数据没有更多'.tr, - failedText: '数据获取失败更多'.tr, + dragText: FlutterI18n.translate( + context, + "drag_text", + ), + readyText: FlutterI18n.translate( + context, + "ready_text", + ), + processingText: FlutterI18n.translate( + context, + "processing_text", + ), + processedText: FlutterI18n.translate( + context, + "processed_text", + ), + noMoreText: FlutterI18n.translate( + context, + "no_more_text", + ), + failedText: FlutterI18n.translate( + context, + "failed_text", + ), infiniteOffset: null, ), onLoad: () async { @@ -124,7 +146,10 @@ class _SearchBookWindowState extends State child: BookInfoCard(toUse: searchList[index]), onTap: () => BothSideSheet.show( context: context, - title: "书籍详细信息", + title: FlutterI18n.translate( + context, + "library.book_detail", + ), child: BookDetailCard( toUse: searchList[index], ), @@ -147,17 +172,25 @@ class _SearchBookWindowState extends State } else if (isSearching.value) { return const Center(child: CircularProgressIndicator()); } else if (search.value.isNotEmpty) { - return const EmptyListView(text: "没有结果"); + return EmptyListView( + text: FlutterI18n.translate( + context, + "library.no_result", + ), + ); } else { - return const Column( + return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( + const Icon( Icons.search, size: 96, ), - Divider(color: Colors.transparent), - Text("请在上面搜索框搜索"), + const Divider(color: Colors.transparent), + Text(FlutterI18n.translate( + context, + "library.please_search", + )), ], ); } diff --git a/lib/page/login/bottom_buttons.dart b/lib/page/login/bottom_buttons.dart index 46875031..3c5bc7a7 100644 --- a/lib/page/login/bottom_buttons.dart +++ b/lib/page/login/bottom_buttons.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:talker_flutter/talker_flutter.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:watermeter/repository/logger.dart'; @@ -23,15 +24,32 @@ class ButtomButtons extends StatelessWidget { alignment: WrapAlignment.center, children: [ TextButton( - child: Text('清除登录缓存', style: _bottomTextStyle), + child: Text( + FlutterI18n.translate(context, "login.clear_cache"), + style: _bottomTextStyle, + ), onPressed: () { NetworkSession().clearCookieJar().then((value) { - if (context.mounted) showToast(context: context, msg: '清理缓存成功'); + if (context.mounted) { + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "login.complete_clear_cache", + ), + ); + } }); }, ), TextButton( - child: Text('查看网络交互', style: _bottomTextStyle), + child: Text( + FlutterI18n.translate( + context, + "login.see_inspector", + ), + style: _bottomTextStyle, + ), onPressed: () { Navigator.of(context).push(MaterialPageRoute( builder: (context) => TalkerScreen(talker: log), diff --git a/lib/page/login/captcha_input_dialog.dart b/lib/page/login/captcha_input_dialog.dart index 52fef75d..c7638839 100644 --- a/lib/page/login/captcha_input_dialog.dart +++ b/lib/page/login/captcha_input_dialog.dart @@ -4,6 +4,7 @@ // A captcha input dialog. import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; class CaptchaInputDialog extends StatelessWidget { @@ -20,7 +21,10 @@ class CaptchaInputDialog extends StatelessWidget { ); return AlertDialog( - title: const Text('请输入验证码'), + title: Text(FlutterI18n.translate( + context, + "login.captcha_window.title", + )), titleTextStyle: const TextStyle( fontSize: 20, color: Colors.black, @@ -35,7 +39,10 @@ class CaptchaInputDialog extends StatelessWidget { style: const TextStyle(fontSize: 20), controller: _captchaController, decoration: InputDecoration( - hintText: "输入验证码", + hintText: FlutterI18n.translate( + context, + "login.captcha_window.hint", + ), fillColor: Colors.grey.withOpacity(0.4), filled: true, contentPadding: const EdgeInsets.symmetric(horizontal: 20), @@ -49,16 +56,28 @@ class CaptchaInputDialog extends StatelessWidget { ), actions: [ TextButton( - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), onPressed: () { Navigator.pop(context); }, ), TextButton( - child: const Text('提交'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), onPressed: () async { if (_captchaController.text.isEmpty) { - showToast(context: context, msg: '请输入验证码'); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "login.captcha_window.message_on_empty", + ), + ); } else { Navigator.of(context).pop(_captchaController.text); } diff --git a/lib/page/login/jc_captcha.dart b/lib/page/login/jc_captcha.dart index f5003117..3cb3526f 100644 --- a/lib/page/login/jc_captcha.dart +++ b/lib/page/login/jc_captcha.dart @@ -9,6 +9,7 @@ import 'dart:typed_data'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:image/image.dart' as img; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/repository/logger.dart'; @@ -244,7 +245,10 @@ class _CaptchaWidgetState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text("服务器认证服务"), + title: Text(FlutterI18n.translate( + context, + "login.slider_title", + )), ), body: FutureBuilder( future: provider, diff --git a/lib/page/login/login_window.dart b/lib/page/login/login_window.dart index d14345a1..a9bb00b4 100644 --- a/lib/page/login/login_window.dart +++ b/lib/page/login/login_window.dart @@ -6,6 +6,7 @@ import 'dart:math'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/repository/logger.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:ming_cute_icons/ming_cute_icons.dart'; @@ -72,7 +73,7 @@ class _LoginWindowState extends State { controller: _idsAccountController, decoration: _inputDecoration( iconData: MingCuteIcons.mgc_user_3_fill, - hintText: "学号", + hintText: FlutterI18n.translate(context, "login.identity_number"), ), style: TextStyle( fontSize: _inputFieldFontSize, @@ -99,7 +100,7 @@ class _LoginWindowState extends State { ), decoration: _inputDecoration( iconData: MingCuteIcons.mgc_safe_lock_fill, - hintText: "一站式登录密码", + hintText: FlutterI18n.translate(context, "login.password"), suffixIcon: IconButton( icon: Icon( _couldNotView ? Icons.visibility : Icons.visibility_off, @@ -147,7 +148,13 @@ class _LoginWindowState extends State { _idsPasswordController.text.isNotEmpty) { await login(); } else { - showToast(context: context, msg: '用户名或密码不符合要求,学号必须 11 位且密码非空'); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "login.incorrect_password_pattern", + ), + ); } }, ), @@ -160,10 +167,18 @@ class _LoginWindowState extends State { bool isGood = true; ProgressDialog pd = ProgressDialog(context: context); pd.show( - msg: '正在登录学校一站式', + msg: FlutterI18n.translate( + context, + "login.on_login_progress", + ), max: 100, hideValue: true, - completed: Completed(completedMsg: "登录成功"), + completed: Completed( + completedMsg: FlutterI18n.translate( + context, + "login.complete_login", + ), + ), ); EhallSession ses = EhallSession(); @@ -219,14 +234,36 @@ class _LoginWindowState extends State { } else if (e is DioException) { if (e.message == null) { if (e.response == null) { - showToast(context: context, msg: "无法连接到服务器。"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "login.failed_login_cannot_connect_to_server", + ), + ); } else { showToast( - context: context, - msg: "请求失败,响应状态码:${e.response!.statusCode}。"); + context: context, + msg: FlutterI18n.translate( + context, + "login.failed_login_with_code", + translationParams: { + "code": e.response!.statusCode.toString() + }, + ), + ); } } else { - showToast(context: context, msg: "请求失败。${e.message}"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "login.failed_login_with_message", + translationParams: { + "message": e.message.toString(), + }, + ), + ); } } else { log.warning( @@ -248,7 +285,10 @@ class _LoginWindowState extends State { ); showToast( context: context, - msg: "未知错误,请联系开发者。", + msg: FlutterI18n.translate( + context, + "login.failed_login_other", + ), ); } } diff --git a/lib/page/schoolcard/school_card_window.dart b/lib/page/schoolcard/school_card_window.dart index b660a56d..b07c1b89 100644 --- a/lib/page/schoolcard/school_card_window.dart +++ b/lib/page/schoolcard/school_card_window.dart @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 // School card log list. +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:calendar_date_picker2/calendar_date_picker2.dart'; @@ -30,9 +31,17 @@ class _SchoolCardWindowState extends State { sumUp += double.parse(element.money); } if (sumUp.isLowerThan(0)) { - return "支出 ${(sumUp * -1).toStringAsFixed(2)}"; + return FlutterI18n.translate( + context, + "school_card_window.income", + translationParams: {"income": (sumUp * -1).toStringAsFixed(2)}, + ); } else { - return "收入 ${sumUp.toStringAsFixed(2)}"; + return FlutterI18n.translate( + context, + "school_card_window.expense", + translationParams: {"expense": sumUp.toStringAsFixed(2)}, + ); } } @@ -57,7 +66,12 @@ class _SchoolCardWindowState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("校园卡流水信息")), + appBar: AppBar( + title: Text(FlutterI18n.translate( + context, + "school_card_window.title", + )), + ), body: Column( children: [ TextButton( @@ -65,10 +79,14 @@ class _SchoolCardWindowState extends State { backgroundColor: Theme.of(context).colorScheme.secondaryContainer, ), - child: Text( - "选择日期:从 ${Jiffy.parseFromDateTime(timeRange[0]!).format(pattern: "yyyy-MM-dd")} " - "到 ${Jiffy.parseFromDateTime(timeRange[1]!).format(pattern: "yyyy-MM-dd")}", - ), + child: Text(FlutterI18n.translate( + context, "school_card_window.select_range", + translationParams: { + "startDay": Jiffy.parseFromDateTime(timeRange[0]!) + .format(pattern: "yyyy-MM-dd"), + "endDay": Jiffy.parseFromDateTime(timeRange[1]!) + .format(pattern: "yyyy-MM-dd"), + })), onPressed: () async { await showCalendarDatePicker2Dialog( context: context, @@ -104,22 +122,36 @@ class _SchoolCardWindowState extends State { columnSpacing: 0, horizontalMargin: 6, columns: [ - const DataColumn2( + DataColumn2( size: ColumnSize.S, label: Center( - child: Text('商户名称'), + child: Text(FlutterI18n.translate( + context, + "school_card_window.store_name", + )), ), ), - const DataColumn2( + DataColumn2( size: ColumnSize.S, label: Center( - child: Text('金额'), + child: Text(FlutterI18n.translate( + context, + "school_card_window.balance", + )), ), ), DataColumn2( size: ColumnSize.L, label: Center( - child: Text('时间(共${moneySunUp(snapshot.data!)}元)'), + child: Text( + FlutterI18n.translate( + context, + "school_card_window.balance", + translationParams: { + "sum": moneySunUp(snapshot.data!) + }, + ), + ), ), ), ], diff --git a/lib/page/setting/about_page/about_page.dart b/lib/page/setting/about_page/about_page.dart index c2bd5ae2..8aa4fa3b 100644 --- a/lib/page/setting/about_page/about_page.dart +++ b/lib/page/setting/about_page/about_page.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:watermeter/page/public_widget/app_icon.dart'; import 'package:watermeter/page/public_widget/re_x_card.dart'; @@ -12,137 +13,224 @@ import 'package:watermeter/page/setting/about_page/developer_widget.dart'; import 'package:watermeter/page/setting/about_page/link_widget.dart'; import 'package:watermeter/repository/preference.dart' as preference; -class AboutPage extends StatelessWidget { - final List getDevelopers = const [ - Developer( - "BenderBlog Rodriguez", - "https://avatars.githubusercontent.com/u/14026321", - "主要开发者,iOS 小部件编写和拼接", - "https://space.bilibili.com/284290692", - ), - Developer( - "BellssGit", - "https://avatars.githubusercontent.com/u/107785251", - "支持:最佳&最久故障反馈者", - "https://space.bilibili.com/17772726", - ), - Developer( - "BrackRat", - "https://avatars.githubusercontent.com/u/35328547", - "设计:主页,登录页,配色,iOS 小部件等", - "https://github.com/BrackRat", - ), - Developer( - "Breezeline", - "https://avatars.githubusercontent.com/u/74224286", - "支持:无价值无意义的产品经理(他自己的描述)", - "mailto:ydzhang.ruc@gmail.com", - ), - Developer( - "0xCAFEBABE", - "https://blog.hxzzz.asia/usr/uploads/2024/05/1717631110.jpg", - "支持:提供彩蛋代码", - "https://blog.hxzzz.asia/", - ), - Developer( - "chitao1234", - "https://avatars.githubusercontent.com/u/25598632", - "开发:修复滑块不对齐问题", - "https://github.com/chitao1234", - ), - Developer( - "Dimole", - "https://avatars.githubusercontent.com/u/24828354", - "支持:辅助修复滑块问题", - "https://github.com/Dimole", - ), - Developer( - "EliteWars", - "https://avatars.githubusercontent.com/u/44139545", - "设计:体育成绩页面", - "https://space.bilibili.com/49892391/", - ), - Developer( - "hhzm (闪电豹猫)", - "https://avatars.githubusercontent.com/u/19224718", - "支持:提供彩蛋代码", - "https://hhzm.win/", - ), - Developer( - "lsy223622 (木生睡不着)", - "https://avatars.githubusercontent.com/u/57913213", - "设计:iOS 图标", - "https://lsy223622.com/", - ), - Developer( - "NanCunChild", - "https://avatars.githubusercontent.com/u/85873278?v=4", - "开发:图书馆搜索功能", - "https://github.com/NanCunChild", - ), - Developer( - "Pairman", - "https://avatars.githubusercontent.com/u/18365163", - "开发:成绩缓存功能和优化滑块算法", - "https://github.com/Pairman", - ), - Developer( - "ReverierXu", - "https://blog.woooo.tech/img/avatar.png", - "设计:用于信息展示的 ReX 卡片", - "https://blog.woooo.tech/", - ), - Developer( - "Ray (Railgun Edition)", - "https://raay.xyz/wp-content/uploads/2023/07/4882705B-3C57-4B46-A3DA-F75C2E0DCE5B.jpeg", - "设计:开屏画面 / 支持:iOS 开发", - "https://raay.xyz/", - ), - Developer( - "stalomeow", - "https://avatars.githubusercontent.com/u/47203031", - "设计:首页时间轴 / 开发:异步登录", - "https://stalomeow.com", - ), - Developer( - "xeonds", - "https://avatars.githubusercontent.com/u/68117734", - "设计:设置页面 / 开发:XDU Planet", - "https://mxts.jiujiuer.xyz", - ), - Developer( - "Xiue233", - "https://xiue233.github.io/images/avatar.png", - "开发:Android 小部件和拼接", - "https://xiue233.github.io/", - ), - Developer( - "ZCWzy", - "https://avatars.githubusercontent.com/u/87163986", - "开发:修复丁香电费 / 支持:研究生版本开发", - "https://github.com/ZCWzy", - ), - ]; +class AboutPage extends StatefulWidget { + const AboutPage({super.key}); - final List linkData = const [ - Link( - icon: Icon(Icons.home), - name: "主页", - url: "https://legacy.superbart.top/xdyou.html", - ), - Link( - icon: Icon(Icons.code), - name: "开源代码", - url: "https://github.com/BenderBlog/traintime_pda", - ), - Link( - icon: Icon(Icons.redeem), - name: "给我捐款", - url: "https://afdian.com/a/benderblog", - ), - ]; + @override + State createState() => _AboutPageState(); +} - const AboutPage({super.key}); +class _AboutPageState extends State { + List getDevelopers() => [ + Developer( + "BenderBlog Rodriguez", + "https://avatars.githubusercontent.com/u/14026321", + FlutterI18n.translate( + context, + "setting.about_page.benderblog", + ), + "https://space.bilibili.com/284290692", + ), + Developer( + "BellssGit", + "https://avatars.githubusercontent.com/u/107785251", + FlutterI18n.translate( + context, + "setting.about_page.bellssgit", + ), + "https://space.bilibili.com/17772726", + ), + Developer( + "BrackRat", + "https://avatars.githubusercontent.com/u/35328547", + FlutterI18n.translate( + context, + "setting.about_page.brackrat", + ), + "https://github.com/BrackRat", + ), + Developer( + "Breezeline", + "https://avatars.githubusercontent.com/u/74224286", + FlutterI18n.translate( + context, + "setting.about_page.breezeline", + ), + "mailto:ydzhang.ruc@gmail.com", + ), + Developer( + "0xCAFEBABE", + "https://blog.hxzzz.asia/usr/uploads/2024/05/1717631110.jpg", + FlutterI18n.translate( + context, + "setting.about_page.cafebabe", + ), + "https://blog.hxzzz.asia/", + ), + Developer( + "chitao1234", + "https://avatars.githubusercontent.com/u/25598632", + FlutterI18n.translate( + context, + "setting.about_page.chitao1234", + ), + "https://github.com/chitao1234", + ), + Developer( + "Dimole", + "https://avatars.githubusercontent.com/u/24828354", + FlutterI18n.translate( + context, + "setting.about_page.dimole", + ), + "https://github.com/Dimole", + ), + Developer( + "EliteWars", + "https://avatars.githubusercontent.com/u/44139545", + FlutterI18n.translate( + context, + "setting.about_page.elitewars", + ), + "https://space.bilibili.com/49892391/", + ), + Developer( + "GodHu777777", + "https://avatars.githubusercontent.com/u/111997394", + FlutterI18n.translate( + context, + "setting.about_page.godhu777777", + ), + "https://github.com/GodHu777777", + ), + Developer( + "Hancl777", + "https://avatars.githubusercontent.com/u/74408609", + FlutterI18n.translate( + context, + "setting.about_page.hancl777", + ), + "https://github.com/Hancl777", + ), + Developer( + "hhzm (闪电豹猫)", + "https://avatars.githubusercontent.com/u/19224718", + FlutterI18n.translate( + context, + "setting.about_page.hhzm", + ), + "https://hhzm.win/", + ), + Developer( + "lsy223622 (木生睡不着)", + "https://avatars.githubusercontent.com/u/57913213", + FlutterI18n.translate( + context, + "setting.about_page.lsy223622", + ), + "https://lsy223622.com/", + ), + Developer( + "NanCunChild", + "https://avatars.githubusercontent.com/u/85873278?v=4", + FlutterI18n.translate( + context, + "setting.about_page.nancunchild", + ), + "https://github.com/NanCunChild", + ), + Developer( + "Pairman", + "https://avatars.githubusercontent.com/u/18365163", + FlutterI18n.translate( + context, + "setting.about_page.pairman", + ), + "https://github.com/Pairman", + ), + Developer( + "ReverierXu", + "https://blog.woooo.tech/img/avatar.png", + FlutterI18n.translate( + context, + "setting.about_page.reverierxu", + ), + "https://blog.woooo.tech/", + ), + Developer( + "Ray (Elliot Edition)", + "https://raay.xyz/wp-content/uploads/2023/07/4882705B-3C57-4B46-A3DA-F75C2E0DCE5B.jpeg", + FlutterI18n.translate( + context, + "setting.about_page.ray", + ), + "https://raay.xyz/", + ), + Developer( + "shadowyingyi", + "https://avatars.githubusercontent.com/u/42831635", + FlutterI18n.translate( + context, + "setting.about_page.shadowyingyi", + ), + "https://github.com/shadowyingyi", + ), + Developer( + "stalomeow", + "https://avatars.githubusercontent.com/u/47203031", + FlutterI18n.translate( + context, + "setting.about_page.stalomeow", + ), + "https://stalomeow.com", + ), + Developer( + "xeonds", + "https://avatars.githubusercontent.com/u/68117734", + FlutterI18n.translate( + context, + "setting.about_page.xeonds", + ), + "https://mxts.jiujiuer.xyz", + ), + Developer( + "Xiue233", + "https://xiue233.github.io/images/avatar.png", + FlutterI18n.translate( + context, + "setting.about_page.xiue233", + ), + "https://xiue233.github.io/", + ), + Developer( + "ZCWzy", + "https://avatars.githubusercontent.com/u/87163986", + FlutterI18n.translate( + context, + "setting.about_page.zcwzy", + ), + "https://github.com/ZCWzy", + ), + ]; + + List linkData() => [ + Link( + icon: const Icon(Icons.home), + name: FlutterI18n.translate( + context, + "setting.about_page.homepage", + ), + url: "https://legacy.superbart.top/xdyou.html", + ), + Link( + icon: const Icon(Icons.code), + name: FlutterI18n.translate( + context, + "setting.about_page.code", + ), + url: "https://github.com/BenderBlog/traintime_pda", + ), + ]; Widget _title(context) => [ const AppIconWidget(), @@ -163,8 +251,8 @@ class AboutPage extends StatelessWidget { ), TextSpan( text: Platform.isIOS || Platform.isMacOS - ? "Te o toriatte Edition" - : "Let Us Cling Together Edition", + ? "Babe I'm Gonna Leave You Edition" + : "May You Never Edition", style: const TextStyle(fontSize: 16), ), ], @@ -181,27 +269,27 @@ class AboutPage extends StatelessWidget { ); Widget get _developerList => ReXCard( - title: Text("Made with love from ${getDevelopers.length} people") + title: Text("Made with love from ${getDevelopers().length} people") .padding( bottom: 8, ) .center(), remaining: const [], - bottomRow: getDevelopers + bottomRow: getDevelopers() .map((e) => DeveloperWidget(developer: e)) .toList() .toColumn(), ); Widget _moreList(context) => ReXCard( - title: const Text("知道更多") + title: Text(FlutterI18n.translate(context, "setting.about_page.title")) .padding( bottom: 8, ) .center(), remaining: const [], bottomRow: [ - ...linkData.map((e) => LinkWidget( + ...linkData().map((e) => LinkWidget( icon: e.icon, name: e.name, url: e.url, @@ -210,7 +298,12 @@ class AboutPage extends StatelessWidget { minLeadingWidth: 0, contentPadding: EdgeInsets.zero, leading: const Icon(Icons.balance), - title: const Text("开源协议和授权信息"), + title: Text( + FlutterI18n.translate( + context, + "setting.about_page.know_more", + ), + ), onTap: () => showLicensePage( context: context, applicationName: Platform.isIOS || Platform.isMacOS @@ -218,30 +311,32 @@ class AboutPage extends StatelessWidget { : "Traintime PDA", applicationVersion: "v${preference.packageInfo.version}+" "${preference.packageInfo.buildNumber}", - applicationLegalese: - "本软件拷贝基于 traintime_pda 代码(或称 watermeter 代码)编译," - "代码按照 Mozilla Public License, v. 2.0 授权。\n\n" - "本程序和西安电子科技大学,体适能服务,书蜗,电表等服务无关。\n\n" - "Copyright 2023-Present BenderBlog Rodriguez and contributors. " - "The Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. " - "If a copy of the MPL was not distributed with this file, " - "You can obtain one at https://mozilla.org/MPL/2.0/.", + applicationLegalese: FlutterI18n.translate( + context, + "setting.setting.about_page.copyright_notice", + ), ), ), if (Platform.isIOS || Platform.isMacOS) - const ListTile( + ListTile( minLeadingWidth: 0, contentPadding: EdgeInsets.zero, - leading: Icon(Icons.code), - title: Text("备案号"), - subtitle: Text("陕ICP备2024026116号-1A"), + leading: const Icon(Icons.code), + title: Text(FlutterI18n.translate( + context, + "setting.about_page.beian", + )), + subtitle: const Text("陕ICP备2024026116号-1A"), ), if (Platform.isAndroid) ListTile( minLeadingWidth: 0, contentPadding: EdgeInsets.zero, leading: const Icon(Icons.code), - title: const Text("安卓签名"), + title: Text(FlutterI18n.translate( + context, + "setting.about_page.sign_android", + )), subtitle: Text(preference.packageInfo.buildSignature), ), ].toList().toColumn(), @@ -250,7 +345,14 @@ class AboutPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("关于本软件")), + appBar: AppBar( + title: Text( + FlutterI18n.translate( + context, + "setting.about_page.title", + ), + ), + ), body: Builder(builder: (context) { if (MediaQuery.sizeOf(context).width > 600 && MediaQuery.sizeOf(context).width / diff --git a/lib/page/setting/about_page/easter_egg_page.dart b/lib/page/setting/about_page/easter_egg_page.dart index e596ff09..08d7524d 100644 --- a/lib/page/setting/about_page/easter_egg_page.dart +++ b/lib/page/setting/about_page/easter_egg_page.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:pinyin/pinyin.dart'; @@ -185,32 +186,135 @@ class EasterEggPage extends StatefulWidget { } class _EasterEggPageState extends State { - final String urlApple = "https://www.bilibili.com/video/BV1mN411C7QV/"; + // Babe I am leaving you, for myself... + // God damn, where's my babe + final String urlApple = "https://www.bilibili.com/video/BV1Td8ceJEFb/"; - final String urlOthers = "https://www.bilibili.com/video/BV1mN411C7QV/"; + final String urlOthers = "https://www.bilibili.com/video/BV1HN411Y7Ct?p=7/"; TextEditingController inputController = TextEditingController( - text: ''' -Let us cling together as the years go by, -Oh my love, my love, -In the quiet of the night -Let our candle always burn, -Let us never lose the lessons we have learned. - -手を取り合って このまま行こう -愛する人よ -静かな宵に -光を灯し -愛しき教えを抱き - -让我们随着时间一起手牵手 -我的爱人 -在夜深之时 -我们的光芒永现 -不要忘记来时的荆棘丛生 - -Brain May and The Queens -A Day at the Races, 1976 + text: Platform.isIOS + ? ''' +for myself... + +[Verse 1] +Babe, baby, baby, I'm gonna leave you +I said baby, you know I'm gonna leave you +I'll leave you when the summertime +Leave you when the summer comes a-rollin' +Leave you when the summer comes along + +我的宝贝,我将在夏季结束之时离开你 + +[Verse 2] +Babe, babe, babe, babe, babe, babe, baby +Baby, I wanna leave you +I ain't joking' woman, I've got to ramble +Oh, yeah, baby, baby, I believin' +We really got to ramble (I can hear it callin' me) +I can hear it callin' me the way it used to do +I can hear it callin' me back home + +我要去探求未知,他跟往常一样让我回到之前 + +[Bridge] +Oh, babe, I'm gonna leave you +Oh, baby, you know +I've really got to leave you +Oh, I can hear it callin' me +I said don't you hear it callin' me the way it used to do? +Ooohh + +我听到他让我回到之前了,你听不到吗 + +[Verse 3] +I know, I know, I know I never, never, never, never, never +Gonna leave you, babe +But I got to go away from this place +I've got to quit you, yeah +Oh, baby, baby, baby, baby, baby, baby, baby +Oh, don't you hear it callin' me? + +我真的一点 一点 一点都不想离开你啊 +但我真的要走了,那催促声你听不到吗 + +Woman, woman, I know, I know +It feels good to have you back again +And I know that one day, baby +It's gonna really grow, yes it is +We gonna go walkin' through the park +Every day + +我明白,我们俩还会再见,在春天万物复苏的时候 +到那时,我们再不分开的样子多好啊 + +Come what may, every day, oh +My, my, my, my, my, my babe +I'm gonna leave you, go away + +每天不分开,但我现在不得不离开你了啊 + +[Bridge] +Oh, I miss you, baby +It was really, really good +You made me happy every single day +But now, I've got to go away +Ooh, oh, oh + +我已经怀念你,每天你是我的光 +但我必须得走了 + +[Outro] +Baby, baby, baby +That's when it's callin' me +I said that's when it's callin' me +Back home + +宝贝啊 宝贝啊 这就是催促我回到之前的 声音啊 + +Babe I’m Gonna Leave You +by Anne Bredon +arranged by Jimmy Page and Robert Plant +from Led Zeppelin, 1969 + +Ray and Elliot are thinking about pulling request for Partner Classtable privately for my program since July, 2024 +''' + : ''' +And may you never lay your head down +Without a hand to hold +May you never make your bed out in the cold + +You’re just like a great strong brother of mine +You know that I love you true +And you never talk dirty behind my back +And I know that there’s those that do + +Oh please won’t you, please won’t you +Bear it in mind +Love is a lesson to learn in our time +Now please won’t you, please won’t you +Bear it in mind for me + +请你不要在无人支持时低下头颅 +愿你不要孤身一人 +你就像我坚强的哥哥 +我真的爱你 +有人在背后说我的坏话 +而你从不 + + +请你不要忘记 +爱是你我生命中的必修课 +不 +请你不要 请你不要 请你不要忘记 +请你 +牢记在心 + +John Martyn, covered by Eric Clapton +Slowhand, 1977 + +Translated by Ray (Elliot Edition) +Ray and Elliot are thinking about pulling request for Partner Classtable privately for my program since July, 2024 ''', ); @@ -248,7 +352,14 @@ A Day at the Races, 1976 @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("你找到了彩蛋")), + appBar: AppBar( + title: Text( + FlutterI18n.translate( + context, + "setting.easter_egg_page.title", + ), + ), + ), body: [ const SizedBox(height: 16.0), TextFormField( @@ -272,7 +383,10 @@ A Day at the Races, 1976 [ TextButton( onPressed: onSubmitted, - child: const Text("加密上面的文本"), + child: Text(FlutterI18n.translate( + context, + "setting.easter_egg_page.encrypt", + )), ), TextButton( onPressed: () => launchUrl( @@ -281,7 +395,10 @@ A Day at the Races, 1976 ), mode: LaunchMode.externalApplication, ), - child: const Text("听歌时间"), + child: Text(FlutterI18n.translate( + context, + "setting.easter_egg_page.listen", + )), ), ].toRow(mainAxisAlignment: MainAxisAlignment.center), const SizedBox(height: 8), diff --git a/lib/page/setting/dialogs/change_brightness_dialog.dart b/lib/page/setting/dialogs/change_brightness_dialog.dart index 24c7b33a..3d223517 100644 --- a/lib/page/setting/dialogs/change_brightness_dialog.dart +++ b/lib/page/setting/dialogs/change_brightness_dialog.dart @@ -2,10 +2,10 @@ // SPDX-License-Identifier: MPL-2.0 // Change app brightness. +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; -import 'package:watermeter/themes/demo_blue.dart'; import 'package:watermeter/controller/theme_controller.dart'; import 'package:watermeter/repository/preference.dart' as preference; @@ -19,8 +19,26 @@ class ChangeBrightnessDialog extends StatefulWidget { class _ChangeBrightnessDialogState extends State { @override Widget build(BuildContext context) { + List demoBlueModeName = [ + FlutterI18n.translate( + context, + "setting.change_brightness_dialog.follow_setting", + ), + FlutterI18n.translate( + context, + "setting.change_brightness_dialog.day_mode", + ), + FlutterI18n.translate( + context, + "setting.change_brightness_dialog.night_mode", + ), + ]; + return AlertDialog( - title: const Text('颜色设置'), + title: Text(FlutterI18n.translate( + context, + "setting.change_brightness_dialog.title", + )), titleTextStyle: TextStyle( fontSize: 20, color: Theme.of(context).colorScheme.onSurface, @@ -49,7 +67,10 @@ class _ChangeBrightnessDialogState extends State { ), actions: [ TextButton( - child: const Text('改完了'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), onPressed: () { Navigator.pop(context); }, diff --git a/lib/page/setting/dialogs/change_swift_dialog.dart b/lib/page/setting/dialogs/change_swift_dialog.dart index f9d479c0..ba4efa38 100644 --- a/lib/page/setting/dialogs/change_swift_dialog.dart +++ b/lib/page/setting/dialogs/change_swift_dialog.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/repository/preference.dart' as preference; class ChangeSwiftDialog extends StatelessWidget { @@ -27,7 +28,10 @@ class ChangeSwiftDialog extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( - title: const Text('课程偏移设置'), + title: Text(FlutterI18n.translate( + context, + "setting.change_swift_dialog.title", + )), content: TextField( autofocus: true, controller: _getNumberController, @@ -36,20 +40,21 @@ class ChangeSwiftDialog extends StatelessWidget { FilteringTextInputFormatter.allow(RegExp(r'^[-+]?[0-9]*')) ], maxLines: 1, - decoration: const InputDecoration( - hintText: "请在此输入数字", - border: OutlineInputBorder(), + decoration: InputDecoration( + hintText: FlutterI18n.translate( + context, + "setting.change_swift_dialog.input_hint", + ), + border: const OutlineInputBorder(), ), ), actions: [ TextButton( - child: const Text('取消'), - onPressed: () { - Navigator.pop(context); - }, + child: Text(FlutterI18n.translate(context, "cancel")), + onPressed: () => Navigator.pop(context), ), TextButton( - child: const Text('提交'), + child: Text(FlutterI18n.translate(context, "confirm")), onPressed: () async { if (_getNumberController.text.isEmpty) { await preference.setInt(preference.Preference.swift, 0); diff --git a/lib/page/setting/dialogs/electricity_password_dialog.dart b/lib/page/setting/dialogs/electricity_password_dialog.dart index 6be4c3a7..23160560 100644 --- a/lib/page/setting/dialogs/electricity_password_dialog.dart +++ b/lib/page/setting/dialogs/electricity_password_dialog.dart @@ -4,6 +4,7 @@ // Electricity password dialog. import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:watermeter/repository/preference.dart' as preference; @@ -33,42 +34,60 @@ class _ElectricityPasswordDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: const Text('修改电费帐号密码'), + title: Text(FlutterI18n.translate( + context, + "setting.change_electricity_title", + )), content: TextField( autofocus: true, controller: _sportPasswordController, obscureText: _couldView, decoration: InputDecoration( - hintText: "请在此输入密码", + hintText: FlutterI18n.translate( + context, + "setting.change_password_dialog.input_hint", + ), border: const OutlineInputBorder(), suffixIcon: IconButton( - icon: Icon(_couldView ? Icons.visibility : Icons.visibility_off), - onPressed: () { - setState(() { - _couldView = !_couldView; - }); - }), + icon: Icon(_couldView ? Icons.visibility : Icons.visibility_off), + onPressed: () => setState(() => _couldView = !_couldView), + ), ), ), actions: [ TextButton( - child: const Text('取消'), + child: Text( + FlutterI18n.translate( + context, + "cancel", + ), + ), onPressed: () { Navigator.pop(context); }, ), TextButton( - child: const Text('提交'), + child: Text( + FlutterI18n.translate( + context, + "confirm", + ), + ), onPressed: () async { - if (_sportPasswordController.text.isNotEmpty) { - preference.setString( - preference.Preference.electricityPassword, - _sportPasswordController.text, + if (_sportPasswordController.text.isEmpty) { + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.change_password_dialog.blank_input", + ), ); - Navigator.of(context).pop(); - } else { - showToast(context: context, msg: "输入空白!"); } + preference.setString( + preference.Preference.electricityPassword, + _sportPasswordController.text, + ); + Navigator.of(context).pop(); }, ), ], diff --git a/lib/page/setting/dialogs/experiment_password_dialog.dart b/lib/page/setting/dialogs/experiment_password_dialog.dart index e2a86c10..ea7a7d52 100644 --- a/lib/page/setting/dialogs/experiment_password_dialog.dart +++ b/lib/page/setting/dialogs/experiment_password_dialog.dart @@ -4,6 +4,7 @@ // Experiment password dialog. import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:watermeter/repository/preference.dart' as user_perference; @@ -38,13 +39,19 @@ class _ExperimentPasswordDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: const Text('修改物理实验系统密码'), + title: Text(FlutterI18n.translate( + context, + "setting.change_experiment_title", + )), content: TextField( autofocus: true, controller: _experimentPasswordController, obscureText: _couldView, decoration: InputDecoration( - hintText: "请在此输入密码", + hintText: FlutterI18n.translate( + context, + "setting.change_password_dialog.input_hint", + ), border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon(_couldView ? Icons.visibility : Icons.visibility_off), @@ -57,13 +64,19 @@ class _ExperimentPasswordDialogState extends State { ), actions: [ TextButton( - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), onPressed: () { Navigator.pop(context, false); }, ), TextButton( - child: const Text('提交'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), onPressed: () async { if (_experimentPasswordController.text.isNotEmpty) { user_perference.setString( @@ -72,7 +85,13 @@ class _ExperimentPasswordDialogState extends State { ); Navigator.of(context).pop(true); } else { - showToast(context: context, msg: "输入空白!"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.change_password_dialog.blank_input", + ), + ); } }, ), diff --git a/lib/page/setting/dialogs/sport_password_dialog.dart b/lib/page/setting/dialogs/sport_password_dialog.dart index dc04b6e2..0a122ef0 100644 --- a/lib/page/setting/dialogs/sport_password_dialog.dart +++ b/lib/page/setting/dialogs/sport_password_dialog.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:watermeter/page/public_widget/toast.dart'; import 'package:watermeter/repository/preference.dart' as user_perference; @@ -40,13 +41,19 @@ class _SportPasswordDialogState extends State { Widget build(BuildContext context) { return PopScope( child: AlertDialog( - title: const Text('修改体育系统密码'), + title: Text(FlutterI18n.translate( + context, + "setting.change_sport_title", + )), content: TextField( autofocus: true, controller: _sportPasswordController, obscureText: _couldView, decoration: InputDecoration( - hintText: "请在此输入密码", + hintText: FlutterI18n.translate( + context, + "setting.change_password_dialog.input_hint", + ), border: const OutlineInputBorder(), suffixIcon: IconButton( icon: Icon(_couldView ? Icons.visibility : Icons.visibility_off), @@ -60,13 +67,19 @@ class _SportPasswordDialogState extends State { ), actions: [ TextButton( - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), onPressed: () { Navigator.of(context).pop(false); // 返回 false }, ), TextButton( - child: const Text('提交'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), onPressed: () async { if (_sportPasswordController.text.isNotEmpty) { await user_perference.setString( @@ -77,7 +90,13 @@ class _SportPasswordDialogState extends State { Navigator.of(context).pop(true); // 返回 true } } else { - showToast(context: context, msg: "输入空白!"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.change_password_dialog.blank_input", + ), + ); } }, ), diff --git a/lib/page/setting/setting.dart b/lib/page/setting/setting.dart index 828ff43b..ff546f22 100644 --- a/lib/page/setting/setting.dart +++ b/lib/page/setting/setting.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:catcher_2/catcher_2.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:talker_flutter/talker_flutter.dart'; import 'package:watermeter/controller/experiment_controller.dart'; @@ -34,7 +35,6 @@ import 'package:watermeter/page/setting/dialogs/change_swift_dialog.dart'; import 'package:watermeter/repository/network_session.dart'; import 'package:watermeter/repository/xidian_ids/ehall_classtable_session.dart'; import 'package:watermeter/repository/xidian_ids/ehall_score_session.dart'; -import 'package:watermeter/themes/demo_blue.dart'; class SettingWindow extends StatefulWidget { const SettingWindow({super.key}); @@ -61,9 +61,15 @@ class _SettingWindowState extends State { showDialog( barrierDismissible: false, context: context, - builder: (context) => const AlertDialog( - title: Text("请关闭应用"), - content: Text("因为技术限制,用户需要自行关闭窗口,然后重新打开应用。"), + builder: (context) => AlertDialog( + title: Text(FlutterI18n.translate( + context, + "setting.need_close_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "setting.need_close_dialog.content", + )), ), ); } @@ -71,6 +77,20 @@ class _SettingWindowState extends State { @override Widget build(BuildContext context) { + List demoBlueModeName = [ + FlutterI18n.translate( + context, + "setting.change_brightness_dialog.follow_setting", + ), + FlutterI18n.translate( + context, + "setting.change_brightness_dialog.day_mode", + ), + FlutterI18n.translate( + context, + "setting.change_brightness_dialog.night_mode", + ), + ]; return SafeArea( child: Scaffold( body: ListView( @@ -97,20 +117,35 @@ class _SettingWindowState extends State { // 功能1 const SizedBox(height: 20), ReXCard( - title: _buildListSubtitle('关于'), + title: _buildListSubtitle(FlutterI18n.translate( + context, + "setting.about", + )), remaining: const [], bottomRow: Column( children: [ ListTile( - title: const Text("关于本程序"), - subtitle: Text( - '版本号:${preference.packageInfo.version}+${preference.packageInfo.buildNumber}'), + title: Text(FlutterI18n.translate( + context, + "setting.about_this_program", + )), + subtitle: Text(FlutterI18n.translate( + context, + "setting.version", + translationParams: { + "version_code": + '${preference.packageInfo.version}+${preference.packageInfo.buildNumber}', + }, + )), onTap: () => context.pushReplacement(const AboutPage()), trailing: const Icon(Icons.navigate_next), ), const Divider(), ListTile( - title: const Text('用户信息'), + title: Text(FlutterI18n.translate( + context, + "setting.user_info", + )), subtitle: Text( "${preference.getString(preference.Preference.name)} ${preference.getString(preference.Preference.execution)}\n" "${preference.getString(preference.Preference.institutes)} ${preference.getString(preference.Preference.subject)}", @@ -140,11 +175,17 @@ class _SettingWindowState extends State { // ), // ), ReXCard( - title: _buildListSubtitle('界面设置'), + title: _buildListSubtitle(FlutterI18n.translate( + context, + "setting.ui_setting", + )), remaining: const [], bottomRow: Column(children: [ ListTile( - title: const Text('设置深浅色'), + title: Text(FlutterI18n.translate( + context, + "setting.brightness_setting", + )), subtitle: Text(demoBlueModeName[ preference.getInt(preference.Preference.brightness)]), trailing: const Icon(Icons.navigate_next), @@ -156,8 +197,14 @@ class _SettingWindowState extends State { }), const Divider(), ListTile( - title: const Text("简化日程时间轴"), - subtitle: const Text("没有日程时 减少空间占用"), + title: Text(FlutterI18n.translate( + context, + "setting.simplify_timeline", + )), + subtitle: Text(FlutterI18n.translate( + context, + "setting.simplify_timeline_description", + )), trailing: Switch( value: preference.getBool( preference.Preference.simplifiedClassTimeline), @@ -178,12 +225,18 @@ class _SettingWindowState extends State { ), ])), ReXCard( - title: _buildListSubtitle('帐号设置'), + title: _buildListSubtitle(FlutterI18n.translate( + context, + "setting.account_setting", + )), remaining: const [], bottomRow: Column( children: [ ListTile( - title: const Text('体育系统密码设置'), + title: Text(FlutterI18n.translate( + context, + "setting.sport_password_setting", + )), trailing: const Icon(Icons.navigate_next), onTap: () { showDialog( @@ -194,7 +247,10 @@ class _SettingWindowState extends State { }), const Divider(), ListTile( - title: const Text('物理实验系统密码设置'), + title: Text(FlutterI18n.translate( + context, + "setting.experiment_password_setting", + )), trailing: const Icon(Icons.navigate_next), onTap: () { showDialog( @@ -206,8 +262,14 @@ class _SettingWindowState extends State { }), const Divider(), ListTile( - title: const Text('电费帐号密码设置'), - subtitle: const Text('非 123456 请设置'), + title: Text(FlutterI18n.translate( + context, + "setting.electricity_password_setting", + )), + subtitle: Text(FlutterI18n.translate( + context, + "setting.electricity_password_description", + )), trailing: const Icon(Icons.navigate_next), onTap: () { showDialog( @@ -221,12 +283,18 @@ class _SettingWindowState extends State { ), ), ReXCard( - title: _buildListSubtitle('课表相关设置'), + title: _buildListSubtitle(FlutterI18n.translate( + context, + "setting.classtable_setting", + )), remaining: const [], bottomRow: Column( children: [ ListTile( - title: const Text("开启课表背景图"), + title: Text(FlutterI18n.translate( + context, + "setting.background", + )), trailing: Switch( value: preference.getBool(preference.Preference.decorated), @@ -234,11 +302,19 @@ class _SettingWindowState extends State { if (value == true && !preference .getBool(preference.Preference.decoration)) { - showToast(context: context, msg: '你先选个图片罢,就在下面'); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.no_background", + ), + ); } else { setState(() { preference.setBool( - preference.Preference.decorated, value); + preference.Preference.decorated, + value, + ); }); } }, @@ -246,7 +322,10 @@ class _SettingWindowState extends State { ), const Divider(), ListTile( - title: const Text('课表背景图选择'), + title: Text(FlutterI18n.translate( + context, + "setting.choose_background", + )), trailing: const Icon(Icons.navigate_next), onTap: () async { FilePickerResult? result; @@ -254,7 +333,13 @@ class _SettingWindowState extends State { result = await pickFile(type: FileType.image); } on MissingStoragePermissionException { if (context.mounted) { - showToast(context: context, msg: "未获取存储权限,无法读取文件"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.no_permission", + ), + ); } } if (mounted) { @@ -264,11 +349,23 @@ class _SettingWindowState extends State { preference.setBool( preference.Preference.decoration, true); if (context.mounted) { - showToast(context: context, msg: '设定成功'); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.successful_setting", + ), + ); } } else { if (context.mounted) { - showToast(context: context, msg: '你没有选图片捏'); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.failure_setting", + ), + ); } } } @@ -276,16 +373,22 @@ class _SettingWindowState extends State { ), const Divider(), ListTile( - title: const Text("清除所有用户添加课程"), + title: Text(FlutterI18n.translate( + context, + "setting.clear_user_class", + )), trailing: const Icon(Icons.navigate_next), onTap: () => showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text( - "是否要清除所有用户添加课程?" - "这个功能对从学校获取的日程没有影响。", - ), + title: Text(FlutterI18n.translate( + context, + "setting.clear_user_class_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "setting.clear_user_class_dialog.content", + )), actions: [ TextButton( style: TextButton.styleFrom( @@ -295,7 +398,10 @@ class _SettingWindowState extends State { Theme.of(context).colorScheme.onPrimary, ), onPressed: () => Navigator.pop(context), - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), ), TextButton( onPressed: () { @@ -308,10 +414,19 @@ class _SettingWindowState extends State { } Get.find() .updateClassTable(); - showToast(context: context, msg: "已经清除完毕"); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.clear_user_class_dialog.clear", + ), + ); Navigator.pop(context); }, - child: const Text('确定'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), ), ], ), @@ -319,16 +434,22 @@ class _SettingWindowState extends State { ), const Divider(), ListTile( - title: const Text("强制刷新课表"), + title: Text(FlutterI18n.translate( + context, + "setting.class_refresh", + )), trailing: const Icon(Icons.navigate_next), onTap: () => showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text( - "是否要强制刷新课表?同意后," - "将会从学校一站式后端重新获取课表,耗时会比较久。", - ), + title: Text(FlutterI18n.translate( + context, + "setting.class_refresh_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "setting.class_refresh_dialog.content", + )), actions: [ TextButton( style: TextButton.styleFrom( @@ -338,7 +459,10 @@ class _SettingWindowState extends State { Theme.of(context).colorScheme.onPrimary, ), onPressed: () => Navigator.pop(context), - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), ), TextButton( onPressed: () { @@ -346,7 +470,10 @@ class _SettingWindowState extends State { .updateClassTable(isForce: true); Navigator.pop(context); }, - child: const Text('确定'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), ), ], ), @@ -354,10 +481,20 @@ class _SettingWindowState extends State { ), const Divider(), ListTile( - title: const Text('课程偏移设置'), + title: Text(FlutterI18n.translate( + context, + "setting.class_swift", + )), subtitle: Text( - '正数错后开学日期 负数提前开学日期\n' - '目前为 ${preference.getInt(preference.Preference.swift)}', + FlutterI18n.translate( + context, + "setting.class_swift_description", + translationParams: { + "swift": preference + .getInt(preference.Preference.swift) + .toString(), + }, + ), ), trailing: const Icon(Icons.navigate_next), onTap: () { @@ -376,32 +513,48 @@ class _SettingWindowState extends State { ), ), ReXCard( - title: _buildListSubtitle('缓存登录设置'), + title: _buildListSubtitle(FlutterI18n.translate( + context, + "setting.core_setting", + )), remaining: const [], bottomRow: Column( children: [ ListTile( - title: const Text("测试错误拦截器"), + title: Text(FlutterI18n.translate( + context, + "setting.check_catcher", + )), trailing: const Icon(Icons.navigate_next), onTap: () => Catcher2.sendTestException(), ), const Divider(), ListTile( - title: const Text('查看网络拦截器和日志'), + title: Text(FlutterI18n.translate( + context, + "setting.check_logger", + )), trailing: const Icon(Icons.navigate_next), onTap: () => context.push(TalkerScreen(talker: log)), ), const Divider(), ListTile( - title: const Text('清除缓存后重启'), + title: Text(FlutterI18n.translate( + context, + "setting.clear_and_restart", + )), trailing: const Icon(Icons.navigate_next), onTap: () => showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text( - "确定清除缓存后重启程序?", - ), + title: Text(FlutterI18n.translate( + context, + "setting.clear_and_restart_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "setting.clear_and_restart_dialog.content", + )), actions: [ TextButton( style: TextButton.styleFrom( @@ -411,13 +564,21 @@ class _SettingWindowState extends State { Theme.of(context).colorScheme.onPrimary, ), onPressed: () => Navigator.pop(context), - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), ), TextButton( onPressed: () async { ProgressDialog pd = ProgressDialog(context: context); - pd.show(msg: "正在清理缓存"); + pd.show( + msg: FlutterI18n.translate( + context, + "setting.clear_and_restart_dialog.cleaning", + ), + ); try { await NetworkSession().clearCookieJar(); } on PathNotFoundException { @@ -431,11 +592,20 @@ class _SettingWindowState extends State { _removeCache(); if (context.mounted) { - showToast(context: context, msg: '缓存已被清除'); + showToast( + context: context, + msg: FlutterI18n.translate( + context, + "setting.clear_and_restart_dialog.clear", + ), + ); Restart.restartApp(); } }, - child: const Text('确定'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), ), ], ), @@ -443,15 +613,22 @@ class _SettingWindowState extends State { ), const Divider(), ListTile( - title: const Text('退出登录并重启应用'), + title: Text(FlutterI18n.translate( + context, + "setting.logout", + )), trailing: const Icon(Icons.navigate_next), onTap: () => showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: const Text("确认对话框"), - content: const Text( - "确定退出登录?你的所有数据将会被彻底删除!", - ), + title: Text(FlutterI18n.translate( + context, + "setting.logout_dialog.title", + )), + content: Text(FlutterI18n.translate( + context, + "setting.logout_dialog.content", + )), actions: [ TextButton( style: TextButton.styleFrom( @@ -461,13 +638,21 @@ class _SettingWindowState extends State { Theme.of(context).colorScheme.onPrimary, ), onPressed: () => Navigator.pop(context), - child: const Text('取消'), + child: Text(FlutterI18n.translate( + context, + "cancel", + )), ), TextButton( onPressed: () async { ProgressDialog pd = ProgressDialog(context: context); - pd.show(msg: '正在退出登录'); + pd.show( + msg: FlutterI18n.translate( + context, + "logging_out", + ), + ); /// Clean Cookie try { @@ -493,7 +678,10 @@ class _SettingWindowState extends State { Restart.restartApp(); } }, - child: const Text('确定'), + child: Text(FlutterI18n.translate( + context, + "confirm", + )), ), ], ), diff --git a/lib/page/toolbox/toolbox_page.dart b/lib/page/toolbox/toolbox_page.dart index ac0b1fa9..4a43fbd2 100644 --- a/lib/page/toolbox/toolbox_page.dart +++ b/lib/page/toolbox/toolbox_page.dart @@ -4,18 +4,25 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:ming_cute_icons/ming_cute_icons.dart'; import 'package:watermeter/model/toolbox_addresses.dart'; import 'package:watermeter/page/public_widget/context_extension.dart'; import 'package:watermeter/page/toolbox/webview_list_tile.dart'; -class ToolBoxPage extends StatelessWidget { +class ToolBoxPage extends StatefulWidget { const ToolBoxPage({super.key}); + @override + State createState() => _ToolBoxPageState(); +} + +class _ToolBoxPageState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text("其他功能"), + title: I18nText("toolbox.title"), leading: IconButton( icon: Icon( Platform.isIOS || Platform.isMacOS @@ -26,9 +33,76 @@ class ToolBoxPage extends StatelessWidget { ), ), body: ListView( - children: WebViewAddresses.values - .map((e) => WebViewListTile(data: e)) - .toList(), + children: [ + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.payment"), + url: "https://payment.xidian.edu.cn/MNetWorkUI/showPublic", + description: FlutterI18n.translate( + context, + "toolbox.payment_description", + ), + iconData: MingCuteIcons.mgc_exchange_cny_line, + ), + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.repair"), + url: "https://ids.xidian.edu.cn/authserver/login?service=" + "https%3A%2F%2Fids.xidian.edu.cn%2Fauthserver%2Foauth2.0%2F" + "callbackAuthorize%3Fclient_id%3D869608421533880320%26" + "redirect_uri%3Dhttp%253A%252F%252Frepair.xidian.edu.cn%252F" + "appsys%252FxidianCasLogin%252FoauthLogin%26response_type%3D" + "code%26state%3Dhome%26client_name%3DCasOAuthClient", + description: FlutterI18n.translate( + context, + "toolbox.repair_description", + ), + iconData: MingCuteIcons.mgc_tool_line, + ), + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.reserve"), + url: "http://libspace.xidian.edu.cn", + description: FlutterI18n.translate( + context, + "toolbox.reserve_description", + ), + iconData: MingCuteIcons.mgc_building_4_line, + ), + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.mobile"), + url: "https://xxcapp.xidian.edu.cn/site/xidianPage/home", + description: FlutterI18n.translate( + context, + "toolbox.mobile_description", + ), + iconData: MingCuteIcons.mgc_chat_2_line, + ), + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.network"), + url: "https://zfw.xidian.edu.cn", + description: FlutterI18n.translate( + context, + "toolbox.network_description", + ), + iconData: MingCuteIcons.mgc_wifi_line, + ), + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.physics"), + url: "https://experiment-helper.wizzstudio.com/#/", + description: FlutterI18n.translate( + context, + "toolbox.physics_description", + ), + iconData: MingCuteIcons.mgc_counter_2_line, + ), + WebViewAddresses( + name: FlutterI18n.translate(context, "toolbox.discover"), + url: "https://nav.xdruisi.com/", + description: FlutterI18n.translate( + context, + "toolbox.discover_description", + ), + iconData: MingCuteIcons.mgc_web_line, + ), + ].map((e) => WebViewListTile(data: e)).toList(), ), ); } diff --git a/lib/themes/demo_blue.dart b/lib/themes/demo_blue.dart index a665b93b..f705e978 100644 --- a/lib/themes/demo_blue.dart +++ b/lib/themes/demo_blue.dart @@ -4,12 +4,6 @@ import 'package:chinese_font_library/chinese_font_library.dart'; import 'package:flutter/material.dart'; -const demoBlueModeName = [ - "跟随系统", - "白天模式", - "黑夜模式", -]; - const demoBlueModeMap = { 0: ThemeMode.system, 1: ThemeMode.light, diff --git a/pubspec.yaml b/pubspec.yaml index 9977f630..e81331d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -111,4 +111,6 @@ flutter: - assets/icon.png - assets/CP1919.svg.vec - assets/Icon-App-iTunes-Background.png - - assets/flutter_i18n/ + - assets/flutter_i18n/zh_CN.yaml + - assets/flutter_i18n/zh_TW.yaml + - assets/flutter_i18n/zh_SG.json