diff --git a/.crowdin/location_names.csv b/.crowdin/location_names.csv new file mode 100644 index 000000000..a8a3cc0d7 --- /dev/null +++ b/.crowdin/location_names.csv @@ -0,0 +1,371 @@ +key,zh-Hant,en,ja,ko,ru,vi,zh-Hans +連江,連江,Lienchiang,,,,, +宜蘭,宜蘭,Yilan,,,,, +彰化,彰化,Changhua,,,,, +南投,南投,Nantou,,,,, +雲林,雲林,Yunlin,,,,, +屏東,屏東,Pingtung,,,,, +基隆,基隆,Keelung,,,,, +臺北,臺北,Taipei,,,,, +新北,新北,New Taipei,,,,, +臺南,臺南,Tainan,,,,, +桃園,桃園,Taoyuan,,,,, +嘉義,嘉義,Chiayi,,,,, +金門,金門,Kinmen,,,,, +高雄,高雄,Kaohsiung,,,,, +臺東,臺東,Taitung,,,,, +花蓮,花蓮,Hualien,,,,, +澎湖,澎湖,Penghu,,,,, +新竹,新竹,Hsinchu,,,,, +臺中,臺中,Taichung,,,,, +苗栗,苗栗,Miaoli,,,,, +成功,成功,Chenggong,,,,, +佳冬,佳冬,Jiadong,,,,, +麥寮,麥寮,Mailiao,,,,, +綠島,綠島,Lüdao,,,,, +蘭嶼,蘭嶼,Lanyu,,,,, +田中,田中,Tianzhong,,,,, +社頭,社頭,Shetou,,,,, +竹田,竹田,Zhutian,,,,, +萬丹,萬丹,Wandan,,,,, +三灣,三灣,Sanwan,,,,, +峨眉,峨眉,Emei,,,,, +南庄,南庄,Nanzhuang,,,,, +太保,太保,Taibao,,,,, +中埔,中埔,Zhongpu,,,,, +番路,番路,Fanlu,,,,, +水上,水上,Shuishang,,,,, +員林,員林,Yuanlin,,,,, +小港,小港,Xiaogang,,,,, +蘇澳,蘇澳,Su'ao,,,,, +五結,五結,Wujie,,,,, +壯圍,壯圍,Zhuangwei,,,,, +南竿,南竿,Nangan,,,,, +莒光,莒光,Juguang,,,,, +烏坵,烏坵,Wuqiu,,,,, +羅東,羅東,Luodong,,,,, +員山,員山,Yuanshan,,,,, +冬山,冬山,Dongshan,,,,, +三星,三星,Sanxing,,,,, +大同,大同,Datong,,,,, +竹東,竹東,Zhudong,,,,, +新埔,新埔,Xinpu,,,,, +關西,關西,Guanxi,,,,, +湖口,湖口,Hukou,,,,, +芎林,芎林,Qionglin,,,,, +橫山,橫山,Hengshan,,,,, +北埔,北埔,Beipu,,,,, +五峰,五峰,Wufeng,,,,, +龍井,龍井,Longjing,,,,, +大雅,大雅,Daya,,,,, +沙鹿,沙鹿,Shalu,,,,, +梧棲,梧棲,Wuqi,,,,, +湖西,湖西,Huxi,,,,, +金峰,金峰,Jinfeng,,,,, +太麻里,太麻里,Taimali,,,,, +卓蘭,卓蘭,Zhuolan,,,,, +大湖,大湖,Dahu,,,,, +公館,公館,Gongguan,,,,, +銅鑼,銅鑼,Tongluo,,,,, +頭屋,頭屋,Touwu,,,,, +三義,三義,Sanyi,,,,, +西湖,西湖,Xihu,,,,, +造橋,造橋,Zaoqiao,,,,, +獅潭,獅潭,Shitan,,,,, +和美,和美,Hemei,,,,, +線西,線西,Xianxi,,,,, +伸港,伸港,Shengang,,,,, +秀水,秀水,Xiushui,,,,, +花壇,花壇,Huatan,,,,, +芬園,芬園,Fenyuan,,,,, +溪湖,溪湖,Xihu,,,,, +東石,東石,Dongshi,,,,, +大村,大村,Dacun,,,,, +埔鹽,埔鹽,Puyan,,,,, +埔心,埔心,Puxin,,,,, +永靖,永靖,Yongjing,,,,, +二水,二水,Ershui,,,,, +二林,二林,Erlin,,,,, +埤頭,埤頭,Pitou,,,,, +芳苑,芳苑,Fangyuan,,,,, +大城,大城,Dacheng,,,,, +竹塘,竹塘,Zhutang,,,,, +溪州,溪州,Xizhou,,,,, +埔里,埔里,Puli,,,,, +草屯,草屯,Caotun,,,,, +竹山,竹山,Zhushan,,,,, +集集,集集,Jiji,,,,, +名間,名間,Mingjian,,,,, +鹿谷,鹿谷,Lugu,,,,, +中寮,中寮,Zhongliao,,,,, +魚池,魚池,Yuchi,,,,, +國姓,國姓,Guoxing,,,,, +水里,水里,Shuili,,,,, +信義,信義,Xinyi,,,,, +仁愛,仁愛,Ren'ai,,,,, +斗六,斗六,Douliu,,,,, +斗南,斗南,Dounan,,,,, +虎尾,虎尾,Huwei,,,,, +西螺,西螺,Xiluo,,,,, +土庫,土庫,Tuku,,,,, +北港,北港,Beigang,,,,, +古坑,古坑,Gukeng,,,,, +大埤,大埤,Dapi,,,,, +莿桐,莿桐,Citong,,,,, +林內,林內,Linnei,,,,, +二崙,二崙,Erlun,,,,, +崙背,崙背,Lunbei,,,,, +東勢,東勢,Dongshi,,,,, +褒忠,褒忠,Baozhong,,,,, +元長,元長,Yuanchang,,,,, +水林,水林,Shuilin,,,,, +朴子,朴子,Puzi,,,,, +大林,大林,Dalin,,,,, +民雄,民雄,Minxiong,,,,, +溪口,溪口,Xikou,,,,, +新港,新港,Xingang,,,,, +六腳,六腳,Liujiao,,,,, +義竹,義竹,Yizhu,,,,, +鹿草,鹿草,Lucao,,,,, +竹崎,竹崎,Zhuqi,,,,, +梅山,梅山,Meishan,,,,, +大埔,大埔,Dapu,,,,, +阿里山,阿里山,Alishan,,,,, +潮州,潮州,Chaozhou,,,,, +長治,長治,Changzhi,,,,, +麟洛,麟洛,Linluo,,,,, +九如,九如,Jiuru,,,,, +里港,里港,Ligang,,,,, +鹽埔,鹽埔,Yanpu,,,,, +高樹,高樹,Gaoshu,,,,, +萬巒,萬巒,Wanluan,,,,, +內埔,內埔,Neipu,,,,, +新埤,新埤,Xinpi,,,,, +崁頂,崁頂,Kanding,,,,, +南州,南州,Nanzhou,,,,, +琉球,琉球,Liuqiu,,,,, +三地門,三地門,Sandimen,,,,, +霧臺,霧臺,Wutai,,,,, +瑪家,瑪家,Majia,,,,, +泰武,泰武,Taiwu,,,,, +來義,來義,Laiyi,,,,, +春日,春日,Chunri,,,,, +獅子,獅子,Shizi,,,,, +鹿野,鹿野,Luye,,,,, +池上,池上,Chishang,,,,, +延平,延平,Yanping,,,,, +光復,光復,Guangfu,,,,, +瑞穗,瑞穗,Ruisui,,,,, +富里,富里,Fuli,,,,, +馬公,馬公,Magong,,,,, +白沙,白沙,Baisha,,,,, +西嶼,西嶼,Xiyu,,,,, +望安,望安,Wang'an,,,,, +七美,七美,Qimei,,,,, +暖暖,暖暖,Nuannuan,,,,, +大安,大安,Da'an,,,,, +文山,文山,Wenshan,,,,, +鹽埕,鹽埕,Yancheng,,,,, +新興,新興,Xinxing,,,,, +前金,前金,Qianjin,,,,, +前鎮,前鎮,Qianzhen,,,,, +頭城,頭城,Toucheng,,,,, +南澳,南澳,Nan'ao,,,,, +竹北,竹北,Zhubei,,,,, +新豐,新豐,Xinfeng,,,,, +苑裡,苑裡,Yuanli,,,,, +通霄,通霄,Tongxiao,,,,, +竹南,竹南,Zhunan,,,,, +後龍,後龍,Houlong,,,,, +鹿港,鹿港,Lukang,,,,, +福興,福興,Fuxing,,,,, +臺西,臺西,Taixi,,,,, +四湖,四湖,Sihu,,,,, +口湖,口湖,Kouhu,,,,, +布袋,布袋,Budai,,,,, +東港,東港,Donggang,,,,, +枋寮,枋寮,Fangliao,,,,, +新園,新園,Xinyuan,,,,, +林邊,林邊,Linbian,,,,, +車城,車城,Checheng,,,,, +滿州,滿州,Manzhou,,,,, +枋山,枋山,Fangshan,,,,, +牡丹,牡丹,Mudan,,,,, +卑南,卑南,Beinan,,,,, +東河,東河,Donghe,,,,, +吉安,吉安,Ji'an,,,,, +壽豐,壽豐,Shoufeng,,,,, +秀林,秀林,Xiulin,,,,, +楠梓,楠梓,Nanzi,,,,, +鳳山,鳳山,Fengshan,,,,, +大寮,大寮,Daliao,,,,, +大樹,大樹,Dashu,,,,, +大社,大社,Dashe,,,,, +仁武,仁武,Renwu,,,,, +鳥松,鳥松,Niaosong,,,,, +岡山,岡山,Gangshan,,,,, +橋頭,橋頭,Qiaotou,,,,, +燕巢,燕巢,Yanchao,,,,, +田寮,田寮,Tianliao,,,,, +阿蓮,阿蓮,Alian,,,,, +路竹,路竹,Luzhu,,,,, +湖內,湖內,Hunei,,,,, +旗山,旗山,Qishan,,,,, +美濃,美濃,Meinong,,,,, +六龜,六龜,Liugui,,,,, +甲仙,甲仙,Jiaxian,,,,, +杉林,杉林,Shanlin,,,,, +內門,內門,Neimen,,,,, +茂林,茂林,Maolin,,,,, +桃源,桃源,Taoyuan,,,,, +那瑪夏,那瑪夏,Namaxia,,,,, +永和,永和,Yonghe,,,,, +新店,新店,Xindian,,,,, +土城,土城,Tucheng,,,,, +蘆洲,蘆洲,Luzhou,,,,, +五股,五股,Wugu,,,,, +坪林,坪林,Pinglin,,,,, +平溪,平溪,Pingxi,,,,, +烏來,烏來,Wulai,,,,, +豐原,豐原,Fengyuan,,,,, +后里,后里,Houli,,,,, +神岡,神岡,Shengang,,,,, +新社,新社,Xinshe,,,,, +石岡,石岡,Shigang,,,,, +外埔,外埔,Waipu,,,,, +大肚,大肚,Dadu,,,,, +新營,新營,Xinying,,,,, +鹽水,鹽水,Yanshui,,,,, +白河,白河,Baihe,,,,, +後壁,後壁,Houbi,,,,, +麻豆,麻豆,Madou,,,,, +下營,下營,Xiaying,,,,, +六甲,六甲,Liujia,,,,, +官田,官田,Guantian,,,,, +大內,大內,Danei,,,,, +佳里,佳里,Jiali,,,,, +學甲,學甲,Xuejia,,,,, +西港,西港,Xigang,,,,, +新化,新化,Xinhua,,,,, +新市,新市,Xinshi,,,,, +安定,安定,Anding,,,,, +玉井,玉井,Yujing,,,,, +楠西,楠西,Nanxi,,,,, +南化,南化,Nanhua,,,,, +左鎮,左鎮,Zuozhen,,,,, +仁德,仁德,Rende,,,,, +歸仁,歸仁,Guiren,,,,, +關廟,關廟,Guanmiao,,,,, +龍崎,龍崎,Longqi,,,,, +永康,永康,Yongkang,,,,, +北,北,North,,,,, +林園,林園,Linyuan,,,,, +茄萣,茄萣,Qieding,,,,, +永安,永安,Yong'an,,,,, +彌陀,彌陀,Mituo,,,,, +梓官,梓官,Ziguan,,,,, +淡水,淡水,Tamsui,,,,, +瑞芳,瑞芳,Ruifang,,,,, +林口,林口,Linkou,,,,, +三芝,三芝,Sanzhi,,,,, +八里,八里,Bali,,,,, +大甲,大甲,Dajia,,,,, +北門,北門,Beimen,,,,, +安南,安南,Annan,,,,, +蘆竹,蘆竹,Luzhu,,,,, +龜山,龜山,Guishan,,,,, +復興,復興,Fuxing,,,,, +東,東,East,,,,, +西,西,West,,,,, +達仁,達仁,Daren,,,,, +大武,大武,Dawu,,,,, +關山,關山,Guanshan,,,,, +海端,海端,Haiduan,,,,, +香山,香山,Xiangshan,,,,, +礁溪,礁溪,Jiaoxi,,,,, +玉里,玉里,Yuli,,,,, +卓溪,卓溪,Zhuoxi,,,,, +頭份,頭份,Toufen,,,,, +清水,清水,Qingshui,,,,, +南,南,South,,,,, +安平,安平,Anping,,,,, +中西,中西,West Central,,,,, +大溪,大溪,Daxi,,,,, +八德,八德,Bade,,,,, +大園,大園,Dayuan,,,,, +楊梅,楊梅,Yangmei,,,,, +七堵,七堵,Qidu,,,,, +中正,中正,Zhongzheng,,,,, +中山,中山,Zhongshan,,,,, +安樂,安樂,Anle,,,,, +三峽,三峽,Sanxia,,,,, +鶯歌,鶯歌,Yingge,,,,, +中和,中和,Zhonghe,,,,, +樹林,樹林,Shulin,,,,, +深坑,深坑,Shenkeng,,,,, +板橋,板橋,Banqiao,,,,, +石碇,石碇,Shiding,,,,, +新莊,新莊,Xinzhuang,,,,, +泰山,泰山,Taishan,,,,, +三重,三重,Sanchong,,,,, +雙溪,雙溪,Shuangxi,,,,, +貢寮,貢寮,Gongliao,,,,, +汐止,汐止,Xizhi,,,,, +萬里,萬里,Wanli,,,,, +金山,金山,Jinshan,,,,, +石門,石門,Shimen,,,,, +苓雅,苓雅,Lingya,,,,, +三民,三民,Sanmin,,,,, +新屋,新屋,Xinwu,,,,, +觀音,觀音,Guanyin,,,,, +北竿,北竿,Beigan,,,,, +東引,東引,Dongyin,,,,, +烈嶼,烈嶼,Lieyu,,,,, +旗津,旗津,Qijin,,,,, +長濱,長濱,Changbin,,,,, +豐濱,豐濱,Fengbin,,,,, +霧峰,霧峰,Wufeng,,,,, +大里,大里,Dali,,,,, +烏日,烏日,Wuri,,,,, +中,中,Central,,,,, +南屯,南屯,Nantun,,,,, +西屯,西屯,Xitun,,,,, +北屯,北屯,Beitun,,,,, +潭子,潭子,Tanzi,,,,, +萬華,萬華,Wanhua,,,,, +松山,松山,Songshan,,,,, +士林,士林,Shilin,,,,, +北投,北投,Beitou,,,,, +新城,新城,Xincheng,,,,, +善化,善化,Shanhua,,,,, +山上,山上,Shanshang,,,,, +北斗,北斗,Beidou,,,,, +田尾,田尾,Tianwei,,,,, +金沙,金沙,Jinsha,,,,, +金湖,金湖,Jinhu,,,,, +柳營,柳營,Liuying,,,,, +東山,東山,Dongshan,,,,, +七股,七股,Qigu,,,,, +將軍,將軍,Jiangjun,,,,, +鼓山,鼓山,Gushan,,,,, +左營,左營,Zuoying,,,,, +中壢,中壢,Zhongli,,,,, +寶山,寶山,Baoshan,,,,, +恆春,恆春,Hengchun,,,,, +太平,太平,Taiping,,,,, +鳳林,鳳林,Fenglin,,,,, +萬榮,萬榮,Wanrong,,,,, +龍潭,龍潭,Longtan,,,,, +平鎮,平鎮,Pingzhen,,,,, +南港,南港,Nangang,,,,, +內湖,內湖,Neihu,,,,, +金寧,金寧,Jinning,,,,, +金城,金城,Jincheng,,,,, +尖石,尖石,Jianshi,,,,, +泰安,泰安,Tai'an,,,,, +和平,和平,Heping,,,,, +縣,縣,County,,,,, +鄉,鄉,Township,,,,, +鎮,鎮,Town,,,,, +市,市,City,,,,, +區,區,District,,,,, \ No newline at end of file diff --git a/assets/translations/strings.pot b/.crowdin/strings.pot similarity index 70% rename from assets/translations/strings.pot rename to .crowdin/strings.pot index 1fb51a144..a0d88da51 100644 --- a/assets/translations/strings.pot +++ b/.crowdin/strings.pot @@ -1,7 +1,11 @@ -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "" +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "" + #: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "" @@ -14,23 +18,23 @@ msgstr "" msgid "單位" msgstr "" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "" @@ -47,10 +51,10 @@ msgid "天氣警特報" msgstr "" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" +msgid "防災資訊" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" msgstr "" @@ -66,11 +70,11 @@ msgstr "" msgid "設定" msgstr "" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "" @@ -78,23 +82,23 @@ msgstr "" msgid "接收類別" msgstr "" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" msgstr "" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" msgstr "" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" msgstr "" @@ -106,7 +110,7 @@ msgstr "" msgid "發送公告時" msgstr "" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" msgstr "" @@ -118,7 +122,7 @@ msgstr "" msgid "地震速報" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "" @@ -126,7 +130,7 @@ msgstr "" msgid "天氣" msgstr "" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "" @@ -134,24 +138,20 @@ msgstr "" msgid "其他" msgstr "" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "" -"海嘯警報發布時\n" -"沿海地區鄉鎮" +msgid "海嘯警報發布時" msgstr "" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "" -"海嘯警報發布時\n" -"上述除外地區" +msgid "海嘯消息發布時" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 @@ -265,11 +265,11 @@ msgid "所在地(鄉鎮)預估震度 1 以上" msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" +msgid "所在地(鄉鎮)發布防災警訊時" msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" +msgid "所在地(鄉鎮)發布防災資訊時" msgstr "" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 @@ -285,9 +285,11 @@ msgid "" msgstr "" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "" -"所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" msgstr "" #: ./lib/app/settings/unit/page.dart:28 @@ -326,23 +328,23 @@ msgstr "" msgid "來源語言" msgstr "" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "" -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "" "DPIP 作為一款致力於提供即時地震資訊的 " "App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n" @@ -350,39 +352,39 @@ msgid "" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" msgstr "" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" msgstr "" -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" msgstr "" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" msgstr "" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" msgstr "" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "" @@ -466,53 +468,165 @@ msgstr "" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "" -#: ./lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "" -#: ./lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "" -#: ./lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "" "自動定位功能將使用您的裝置上的 GPS,即使 DPIP " "關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "" -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" msgstr "" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" msgstr "" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" msgstr "" -#: ./lib/app/settings/location/select/page.dart:26 -msgid "縣市" +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" msgstr "" #: ./lib/app/settings/location/select/page.dart:38 +msgid "縣市" +msgstr "" + +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" msgstr "" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "" + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" msgstr "" @@ -544,10 +658,6 @@ msgstr "" msgid "使用系統顏色" msgstr "" -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "" - #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "" @@ -560,8 +670,8 @@ msgstr "" msgid "服務區域外,僅在臺灣各地可用" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" msgstr "" #: ./lib/app/home/_widgets/weather_header.dart:127 @@ -572,33 +682,43 @@ msgstr "" msgid "尚未設定所在地" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:874 +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1089 msgid "第 {serial} 報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "" "{time} 左右,{location}附近發生有感地震,預估規模 " "M{magnitude}、所在地最大震度{intensity}。" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "" +"{time} 左右,{location}附近發生有感地震,預估規模 " +"M{magnitude}、深度{depth}公里。" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" msgstr "" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" msgstr "" @@ -614,7 +734,7 @@ msgstr "" msgid "重試" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "" @@ -668,19 +788,15 @@ msgid "" "之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "" @@ -688,175 +804,191 @@ msgstr "" msgid "儲存" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "" -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "" - -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "" - -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "" @@ -916,10 +1048,6 @@ msgstr "" msgid "公告詳情" msgstr "" -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "" - #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" msgstr "" @@ -1202,4 +1330,20 @@ msgstr "" #: ./lib/utils/weather_icon.dart:341 msgid "陰大雷雹" +msgstr "" + +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" msgstr "" \ No newline at end of file diff --git a/.crowdin/weather_station_names.csv b/.crowdin/weather_station_names.csv new file mode 100644 index 000000000..2e5eaac0d --- /dev/null +++ b/.crowdin/weather_station_names.csv @@ -0,0 +1,818 @@ +key,zh-Hant,en,ja,ko,ru,vi,zh-Hans +466850,五分山雷達站,Wufenshan,,,,, +466881,新北,New Taipei,,,,, +466900,淡水,Tamsui,,,,, +466910,鞍部,Anbu,,,,, +466920,臺北,Taipei,,,,, +466930,竹子湖,Zhuzihu,,,,, +466940,基隆,Keelung,,,,, +466950,彭佳嶼,Pengjiayu,,,,, +466990,花蓮,Hualien,,,,, +467050,新屋,Xinwu,,,,, +467080,宜蘭,Yilan,,,,, +467110,金門,Kinmen,,,,, +467270,田中,Tianzhong,,,,, +467280,後龍,Houlong,,,,, +467290,古坑,Gukeng,,,,, +467300,東吉島,Dongjidao,,,,, +467350,澎湖,Penghu,,,,, +467410,臺南,Tainan,,,,, +467420,永康,Yongkang,,,,, +467441,高雄,Kaohsiung,,,,, +467480,嘉義,Chiayi,,,,, +467490,臺中,Taichung,,,,, +467530,阿里山,Alishan,,,,, +467540,大武,Dawu,,,,, +467550,玉山,Yushan,,,,, +467571,新竹,Hsinchu,,,,, +467590,恆春,Hengchun,,,,, +467610,成功,Chenggong,,,,, +467620,蘭嶼,Lanyu,,,,, +467650,日月潭,Sun Moon Lake,,,,, +467660,臺東,Taitung,,,,, +467790,墾丁雷達站,Kenting,,,,, +467990,馬祖,Matsu,,,,, +12J990,口湖工作站,Kouhu Branch Station,,,,, +12Q970,東港工作站,Donggang Branch,,,,, +12Q980,恆春工作站,Hengchun Branch,,,,, +42HA10,萬大發電廠,Wanta Hydro,,,,, +72AI40,桃改樹林分場,Shulin Sub-station Of Taoyuan ARES,,,,, +72C440,桃園農改場,,,,,, +72D080,桃改五峰分場,Wufeng Sub-station Of Taoyuan ARES,,,,, +72D680,桃改新埔分場,Sinpu Sub-station Of Taoyuan ARES,,,,, +72G600,臺中農改場,Ta Tsun,,,,, +72HA00,中改埔里分場,Puli Sub-station Of Taichung ARES,,,,, +72K220,南改斗南分場,Dounan Sub-station Of Tainan ARES,,,,, +72M360,南改義竹分場,Yichu Sub-station Of Tainan ARES,,,,, +72M700,南改鹿草分場,Lucao Sub-station Of Tainan ARES,,,,, +72N100,臺南農改場,Tainan,,,,, +72N240,七股研究中心,Qigu Research Center,,,,, +72Q010,高雄農改場,Pingtung,,,,, +72S200,東改班鳩分場,Banjuou Sub-station Of Taitung ARES ,,,,, +72S590,東改賓朗果園,Binlung Orchard Sub-station Of Taitung ARES ,,,,, +72T250,花蓮農改場,Gi An,,,,, +72U480,花改蘭陽分場,Lanyang Sub-station Of Hualien ARES,,,,, +72V140,高改旗南分場,Chinan Sub-station Of Kaohsiung ARES,,,,, +82A750,茶改北部分場,North Branch Of TBRS,,,,, +82C160,茶改場,Tea And Beverage Research Station,,,,, +82H320,茶改中部分場,Middle Branch Of TRES,,,,, +82H840,茶改南部分場,South Branch Of TBRS,,,,, +82S580,茶改東部分場,East Branch Of TBRS,,,,, +A2C560,農工中心,,,,,, +A2K360,水試臺西試驗場,Taixi Experimental Fishing Ground,,,,, +A2K630,臺大雲林校區,Yunlin Branch Of NTU,,,,, +A2N290,臺南蘭花園區,Taiwan Orchid,,,,, +B2E890,畜試北區分所,North Branch Of TLRI,,,,, +B2N890,畜產試驗所,Hsin Hua,,,,, +B2Q810,畜試南區分所,South Branch Of TLRI,,,,, +B2U990,畜試東區分所,East Branch Of TLRI,,,,, +C2A540,四堵,Sihdu,,,,, +C2A560,福山,Fushan,,,,, +C2A650,火燒寮,Huoshaoliao,,,,, +C2A660,瑞芳,Rueifang,,,,, +C2A880,福隆,Fulong,,,,, +C2A920,富貴角,Fugueijiao,,,,, +C2C410,中央大學,Ncu,,,,, +C2D720,關西工作站,Guanxi Experiment Station,,,,, +C2D730,寶山農場,Baoshan Farm,,,,, +C2D740,屯原,Tunyuan,,,,, +C2E520,大湖,Dahu,,,,, +C2E540,龍溪,Longxi,,,,, +C2E880,三義,Sanyi,,,,, +C2E970,八甲,Bajia,,,,, +C2F000,大肚,Dadu,,,,, +C2F860,梨山,Lishan,,,,, +C2F930,大甲,Dajia,,,,, +C2F990,摩天嶺,Motianling,,,,, +C2F9A0,中竹林,Zhongzhulin,,,,, +C2FA00,烏石坑,Wushihkeng,,,,, +C2FB50,出雲,Chuyun,,,,, +C2FB60,頭櫃山,Touguishan,,,,, +C2G640,鹿港,Lukang,,,,, +C2G840,北斗,Beidou,,,,, +C2G870,芳苑,Fangyuan,,,,, +C2G980,田頭村,Toutian Village,,,,, +C2G9A0,畜試所彰化,Changhua Branch Of TLRI,,,,, +C2H950,中寮,Zhongliao,,,,, +C2H9D0,三隻寮,Sanziliao,,,,, +C2H9E0,國姓南港,Guoxing Nangang,,,,, +C2H9F0,柑林,Ganlin,,,,, +C2H9G0,百勝,Bosheng,,,,, +C2H9H0,苗改南投蜂場,Nantou Bee Farm Of Miaoli TARI,,,,, +C2H9J0,中台,Zhongtai,,,,, +C2H9L0,馬烈霸,Malieba,,,,, +C2H9M0,發祥,Faxiang,,,,, +C2H9N0,仁愛東眼,Renaidong,,,,, +C2H9P0,伊拿谷,Yinagu,,,,, +C2H9Q0,北東眼山,Beidongyanshan,,,,, +C2H9R0,卓社,Zhuoshe,,,,, +C2H9S0,龍南,Longnan,,,,, +C2H9T0,名間竹圍,Mingjianzhuwei,,,,, +C2H9U0,鳳鵬,Fengpeng,,,,, +C2H9W0,大坪頂農水,Dapingding Station,,,,, +C2I090,鳳凰,Fenghuang,,,,, +C2K240,草嶺,Caoling,,,,, +C2K610,草嶺石壁,Caolingshibi,,,,, +C2K620,馬光農場,Maguang Organic Agriculture Circular Park,,,,, +C2K630,荷苞,Hebao,,,,, +C2M410,馬頭山,Matoushan,,,,, +C2M620,瑞里,Ruili,,,,, +C2M910,嘉義大學,Chiayi University,,,,, +C2M920,朴子農改,Pozi DARES,,,,, +C2M930,石卓,Shizhuo,,,,, +C2M940,日野賀,Riyehe,,,,, +C2M950,太和,Taihe,,,,, +C2M960,外寮,Wailiao,,,,, +C2M970,碧湖,Bihu,,,,, +C2N160,西拉雅風管處,Siraya NSAH,,,,, +C2O810,曾文,Cengwen,,,,, +C2O930,玉井,Yujing,,,,, +C2O950,安南,Annan,,,,, +C2R170,屏東,Pingdong,,,,, +C2R970,屏科大,National Pingtung University,,,,, +C2V250,甲仙,Jiaxian,,,,, +C2V260,月眉,Yuemei,,,,, +C2V310,美濃,Meinong,,,,, +C2W030,金門農試所,Kimmann,,,,, +C2W230,畜試所澎湖,Penghu Field Area Of TLRI,,,,, +CAG100,王功漁港,Wanggong Fishing Port,,,,, +CAH030,茶改場竹圍站,TRES Chuwei Station,,,,, +CAJ050,海口故事園區,Haikou Story Camping Park,,,,, +CAL110,布袋國中,Budai Junior High School,,,,, +CAN130,水試所海水繁養殖中心,Mariculture Research Center,,,,, +CAN140,六官養殖協會,Liuguan Aquaculture,,,,, +CAQ030,崎峰國小,Cifong Elementary School,,,,, +E2H360,蓮華池,Lienhuchih,,,,, +E2HA20,林試畢祿溪站,Pilushi,,,,, +E2K600,四湖植物園,Sihu Botanical Garden,,,,, +E2P980,林試六龜中心,Lioukuei Research Center ,,,,, +E2P990,林試扇平站,Shanping,,,,, +E2S960,林試太麻里2,Taimalee2,,,,, +E2S980,林試太麻里1,Taimalee Research Center 1,,,,, +G2AI50,關渡,Guandu,,,,, +G2F820,農試所(霧峰),Taichung,,,,, +G2L020,農試嘉義分所,Chiayi Sub-station Of TARI,,,,, +G2M350,農試溪口農場,Xikou Farm Of TARI,,,,, +G2P820,農試鳳山分所,Fengshan Tropical Horticultural Of TARI,,,,, +K2E360,苗栗農改場,,,,,, +K2E710,苗改生物防治研究中心,Biological Control Branch Of Miaoli TARI,,,,, +K2F750,種苗改良場,Shin She,,,,, +U2H480,溪頭,Hsi Tou,,,,, +U2HA30,臺大和社,NTU Exfohoshe,,,,, +U2HA40,臺大內茅埔,NTU Exfoneimoupu,,,,, +U2HA50,臺大竹山,NTU Experimental Forest,,,,, +V2C250,八德合作社,Bade Cooperative,,,,, +V2C260,八德蔬果,Bade Fruit And Vegetable,,,,, +V2K610,大庄合作社,Dazhuang Cooperative,,,,, +V2K620,麥寮合作社,Mailiao Cooperative,,,,, +C0A520,山佳,Shanjia,,,,, +C0A530,坪林,Pinglin,,,,, +C0A550,泰平,Taiping,,,,, +C0A570,桶後,Tonghou,,,,, +C0A640,石碇,Shihding,,,,, +C0A770,科教館,Science Education Center ,,,,, +C0A860,大坪,Daping,,,,, +C0A870,五指山,Wujhihshan,,,,, +C0A890,雙溪,Shuangsi,,,,, +C0A931,三和,Sanhe,,,,, +C0A940,金山,Jinshan,,,,, +C0A950,鼻頭角,Bitoujiao,,,,, +C0A970,三貂角,Sandiaojiao,,,,, +C0A980,社子,Shezih,,,,, +C0A9C0,天母,Tianmu,,,,, +C0A9F0,內湖,Neihu,,,,, +C0AC40,大屯山,Datunshan,,,,, +C0AC60,三峽,Sanshia,,,,, +C0AC70,信義,Xinyi,,,,, +C0AC80,文山,Wenshan,,,,, +C0ACA0,新莊,Xinzhuang,,,,, +C0AD10,八里,Bali,,,,, +C0AD30,蘆洲,Lujhou,,,,, +C0AD40,土城,Tucheng,,,,, +C0AD50,鶯歌,Yingge,,,,, +C0AG80,中和,Zhonghe,,,,, +C0AH00,汐止,Xizhi,,,,, +C0AH10,永和,Yonghe,,,,, +C0AH30,五分山,Wufengshan,,,,, +C0AH40,平等,Pingdeng,,,,, +C0AH50,林口,Linkou,,,,, +C0AH70,松山,Songshan,,,,, +C0AH80,深坑,Shenkeng,,,,, +C0AH90,福山植物園,Fushan Botanical Garden,,,,, +C0AI00,五股,Wugu,,,,, +C0AI10,屈尺,Quchi,,,,, +C0AI20,白沙灣,Baishawan,,,,, +C0AI30,三重,Sanchong,,,,, +C0AI40,石牌,Shipai,,,,, +C0AJ20,野柳,Yehliou,,,,, +C0AJ30,淡水觀海,Danshuei Guanhai,,,,, +C0AJ40,石門,Shimen,,,,, +C0AJ50,水湳洞,Shuinandong,,,,, +C0AJ60,六塊厝,Lioukuaitsuo,,,,, +C0AJ70,田寮,Tianliao,,,,, +C0AJ80,板橋,Banchiao,,,,, +C0AJ90,澳底,Aodi,,,,, +C0AK10,太平里,Taiping Vil.,,,,, +C0AK30,硬漢嶺,Yinghanling,,,,, +C0B010,七堵,Qidu,,,,, +C0B020,基隆嶼,Keelung Islet,,,,, +C0B040,大武崙,Dawulun,,,,, +C0B050,八斗子,Badouzi,,,,, +C0B060,暖暖,Nuannuan,,,,, +C0C460,復興,Fuxing,,,,, +C0C480,桃園,Taoyuan,,,,, +C0C490,八德,Bade,,,,, +C0C590,觀音,Guanyin,,,,, +C0C620,蘆竹,Luzhu,,,,, +C0C630,大溪,Dasi,,,,, +C0C650,平鎮,Pingjhen,,,,, +C0C660,楊梅,Yangmei,,,,, +C0C670,龍潭,Longtan,,,,, +C0C680,龜山,Guishan,,,,, +C0C700,中壢,Zhongli,,,,, +C0C710,大溪永福,Yongfu Daxi,,,,, +C0C720,竹圍,Jhuwei,,,,, +C0C730,中大臨海站,Jhongda Coastal Station,,,,, +C0C740,觀音工業區,Guanyin Industrial Area,,,,, +C0C750,新興坑尾,Sinsingkengwei,,,,, +C0C790,東眼山,Dongyanshan,,,,, +C0C800,四稜,Sileng,,,,, +C0D360,梅花,Meihua,,,,, +C0D430,峨眉,Emei,,,,, +C0D480,打鐵坑,Datiekeng,,,,, +C0D540,橫山,Hengshan,,,,, +C0D550,雪霸,Xueba,,,,, +C0D560,竹東,Zhudong,,,,, +C0D580,寶山,Baoshan,,,,, +C0D590,新豐,Sinfong,,,,, +C0D650,湖口,Hukou,,,,, +C0D660,新竹市東區,Dongqu Hsinshu City,,,,, +C0D670,海天一線,Haitianyisian,,,,, +C0D680,香山濕地,Siangshan Wetland,,,,, +C0D690,外湖,Waihu,,,,, +C0D700,關西,Guanxi,,,,, +C0D750,樂山林道6k,Leshan 6k,,,,, +C0D760,大坪苗圃,Daping Nurserygarden,,,,, +C0E420,竹南,Jhunan,,,,, +C0E430,南庄,Nanzhuang,,,,, +C0E550,明德,Mingde,,,,, +C0E570,白沙屯,Baishatun,,,,, +C0E590,通霄,Tongxiao,,,,, +C0E610,馬都安,Madu-An,,,,, +C0E730,頭份,Toufen,,,,, +C0E740,造橋,Zaoqiao,,,,, +C0E750,苗栗,Miaoli,,,,, +C0E780,銅鑼,Tongluo,,,,, +C0E791,卓蘭,Zhuolan,,,,, +C0E810,西湖,Xihu,,,,, +C0E820,獅潭,Shitan,,,,, +C0E830,苑裡,Yuanli,,,,, +C0E850,大河,Dahe,,,,, +C0E870,高鐵苗栗,THSR Miaoli,,,,, +C0E910,海埔,Haipu,,,,, +C0E920,通霄漁港,Tongsiao Fishing Harbor,,,,, +C0E930,龍鳳,Longfong,,,,, +C0E940,雪見,Shiuejian,,,,, +C0E950,松安,Songan,,,,, +C0E960,觀霧分站,Guanwu,,,,, +C0F0A0,雪山圈谷,Xueshanjuangu,,,,, +C0F0B0,石岡,Shigang,,,,, +C0F0C0,中坑,Zhongkeng,,,,, +C0F0D0,審馬陣,Shenmazhen,,,,, +C0F0E0,南湖圈谷,Nanhuquangu,,,,, +C0F850,東勢,Dongshi,,,,, +C0F970,大坑,Dakeng,,,,, +C0F9I0,神岡,Shengang,,,,, +C0F9K0,大安,Da-An,,,,, +C0F9L0,后里,Houli,,,,, +C0F9M0,豐原,Fengyuan,,,,, +C0F9N0,大里,Dali,,,,, +C0F9O0,潭子,Tanzi,,,,, +C0F9P0,清水,Qingshui,,,,, +C0F9Q0,外埔,Waipu,,,,, +C0F9R0,龍井,Longjing,,,,, +C0F9S0,烏日,Wuri,,,,, +C0F9T0,西屯,Xitun,,,,, +C0F9U0,南屯,Nantun,,,,, +C0F9V0,新社,Xinshe,,,,, +C0F9X0,大雅(中科園區),Daya,,,,, +C0F9Y0,桃山,Taoshan,,,,, +C0F9Z0,雪山東峰,Xueshandongfeng,,,,, +C0FA10,松柏,Songbai,,,,, +C0FA20,溫寮,Wunliao,,,,, +C0FA30,梧棲,Wuqi,,,,, +C0FA40,臺中電廠,Taichung?Power Plant,,,,, +C0FA50,霧峰,Wufeng,,,,, +C0FA60,鞍馬山工作站,Anmashan Office,,,,, +C0FA70,大雪山埡口,Dashiueshan Yakou,,,,, +C0FA80,小雪山天池,Shiaushiueshan Tianchr,,,,, +C0FA90,小雪山林道,Shiaushiueshan,,,,, +C0FB00,大雪山,Dashiueshan,,,,, +C0FB10,出雲山苗圃,Chuyunshan,,,,, +C0FB20,雪山橋,Shiueshanchiau,,,,, +C0FB30,八仙山苗圃,Bashianshan,,,,, +C0FB40,中橫21.6k,Chungheng 21.6k,,,,, +C0FB70,大甲溪埔,"Dajia, Xipu",,,,, +C0G620,芬園,Fenyuan,,,,, +C0G650,員林,Yuanlin,,,,, +C0G660,溪湖,Xihu,,,,, +C0G720,溪州,Xizhou,,,,, +C0G730,二林,Erlin,,,,, +C0G740,大城,Dacheng,,,,, +C0G770,福興,Fuxing,,,,, +C0G780,秀水,Xiushui,,,,, +C0G800,埔鹽,Puyan,,,,, +C0G810,埔心,Puxin,,,,, +C0G820,田尾,Tianwei,,,,, +C0G830,埤頭,Pitou,,,,, +C0G860,社頭,Shetou,,,,, +C0G880,二水,Ershui,,,,, +C0G890,伸港,Shenggang,,,,, +C0G900,線西,Xianxi,,,,, +C0G910,花壇,Huatan,,,,, +C0G920,永靖,Yongjing ,,,,, +C0G940,竹塘,Zhutang,,,,, +C0G950,防潮門,Fangchaomen,,,,, +C0G960,福寶,Fubao,,,,, +C0G970,三豐,Sanfong,,,,, +C0G9B0,和美,Hemei,,,,, +C0H890,埔里,Puli,,,,, +C0H960,草屯,Caotun,,,,, +C0H990,昆陽,Kunyang,,,,, +C0H9A0,神木村,Shenmu Village,,,,, +C0H9C0,合歡山,Hehuan Mountain,,,,, +C0I010,廬山,Lushan,,,,, +C0I080,信義,Xinyi,,,,, +C0I110,竹山,Zhushan,,,,, +C0I360,水里,Shuili,,,,, +C0I370,魚池,Yuchi,,,,, +C0I380,集集,Jiji,,,,, +C0I390,仁愛,Ren'Ai,,,,, +C0I410,名間,Mingjian,,,,, +C0I420,國姓,Guoxing,,,,, +C0I460,南投,Nantou,,,,, +C0I480,梅峰,Meifeng,,,,, +C0I490,萬大林道,Wandalindao,,,,, +C0I520,玉山風口,Yushanfengkou,,,,, +C0I530,小奇萊,Xiaoqilai,,,,, +C0I540,奇萊稜線,Qilailengxian,,,,, +C0K250,崙背,Lunbei,,,,, +C0K280,四湖,Sihu,,,,, +C0K291,宜梧,Yiwu,,,,, +C0K330,虎尾,Huwei,,,,, +C0K390,土庫,Tuku,,,,, +C0K400,斗六,Douliu,,,,, +C0K410,北港,Beigang,,,,, +C0K420,西螺,Xiluo,,,,, +C0K430,褒忠,Baozhong,,,,, +C0K440,二崙,Erlun,,,,, +C0K450,大埤,Dapi,,,,, +C0K460,斗南,Dounan,,,,, +C0K470,林內,Linnei,,,,, +C0K480,莿桐,Citong,,,,, +C0K500,元長,Yuanchang,,,,, +C0K510,水林,Shuilin,,,,, +C0K530,臺西,Taixi,,,,, +C0K550,蔦松,Niaosong,,,,, +C0K560,棋山,Qishan,,,,, +C0K580,高鐵雲林,THSR Yunlin,,,,, +C0K590,雲林東勢,"Dongshi, Yunlin County",,,,, +C0K600,箔子寮,Bozihliao,,,,, +C0M520,東後寮,Donghouliao,,,,, +C0M530,奮起湖,Fenqihu,,,,, +C0M640,中埔,Zhongpu,,,,, +C0M650,朴子,Puzi,,,,, +C0M660,溪口,Xikou,,,,, +C0M670,大林,Dalin,,,,, +C0M680,太保,Taibao,,,,, +C0M690,水上,Shuishang,,,,, +C0M700,竹崎,Zhuqi,,,,, +C0M710,東石,Dongshi,,,,, +C0M720,番路,Fanlu,,,,, +C0M730,嘉義市東區,Dongqu Chiayi City,,,,, +C0M740,六腳,Liujiao,,,,, +C0M750,布袋,Budai,,,,, +C0M760,民雄,Minxiong,,,,, +C0M770,嘉義梅山,Meishan Chiayi County,,,,, +C0M780,鹿草,Lucao,,,,, +C0M790,新港,Xingang,,,,, +C0M800,茶山,Chashan,,,,, +C0M810,里佳,Lijia,,,,, +C0M820,達邦,Dabang,,,,, +C0M850,表湖,Biaohu,,,,, +C0M860,新美,Shinmei,,,,, +C0M880,好美里,Haomeili,,,,, +C0N010,鯤鯓國小,Kunshen Elementary School,,,,, +C0N020,城西,Chengsi,,,,, +C0N030,四草,Sihtsao,,,,, +C0N040,蘆竹溝,Lujhugou,,,,, +C0N050,蚵寮,Eliao,,,,, +C0O830,北寮,Beiliao,,,,, +C0O840,王爺宮,Wangyegong,,,,, +C0O860,大內,Danei,,,,, +C0O900,善化,Shanhua,,,,, +C0O960,崎頂,Qiding,,,,, +C0O970,虎頭埤,Hutoupi,,,,, +C0O980,新市,Xinshi,,,,, +C0O990,媽廟,Mamiao,,,,, +C0R100,尾寮山,Weiliaoshan,,,,, +C0R130,阿禮,Ali,,,,, +C0R140,瑪家,Majia,,,,, +C0R150,三地門,Sandimen,,,,, +C0R160,鹽埔,Yanpuxinwei,,,,, +C0R190,赤山,Chishan,,,,, +C0R220,潮州,Chaojhou,,,,, +C0R240,來義,Laiyi,,,,, +C0R260,春日,Chunri,,,,, +C0R270,琉球嶼,Liouciouyu,,,,, +C0R280,檳榔,Binlang,,,,, +C0R320,車城,Checheng,,,,, +C0R341,牡丹,Mudan,,,,, +C0R350,貓鼻頭,Maobitou,,,,, +C0R440,大漢山,Dahanshan,,,,, +C0R470,高樹,Gaoshu,,,,, +C0R480,長治,Changzhi,,,,, +C0R490,九如,Jiuru,,,,, +C0R520,崁頂,Kanding,,,,, +C0R540,佳冬,Jiadong,,,,, +C0R550,新埤,Xinpi,,,,, +C0R560,新園,Xinyuan,,,,, +C0R570,麟洛,Linluo,,,,, +C0R580,南州,Nanzhou,,,,, +C0R590,里港,Ligang,,,,, +C0R600,舊泰武,Jiutaiwu,,,,, +C0R620,墾雷,Kenlei,,,,, +C0R640,東港,Donggang,,,,, +C0R650,竹田,Zhutian,,,,, +C0R660,枋寮,Fangliao,,,,, +C0R670,楓港,Fenggang,,,,, +C0R680,佳樂水,Jialeshui,,,,, +C0R690,墾丁,Kenting,,,,, +C0R700,枋山,Fangshan,,,,, +C0R710,龍磐,Longpan,,,,, +C0R720,旭海,Xuhai,,,,, +C0R730,大坪頂,Dapingding,,,,, +C0R741,獅子,Shizi,,,,, +C0R750,四林格山,Silingeshan,,,,, +C0R760,南仁湖,Nanrenhu,,,,, +C0R770,保力,Baoli,,,,, +C0R780,滿州,Manzhou,,,,, +C0R790,九棚,Jiupeng,,,,, +C0R800,丹路,Danlu,,,,, +C0R810,內獅,Neishi,,,,, +C0R820,白鷺,Bailu,,,,, +C0R830,高士,Gaoshi,,,,, +C0R840,牡丹池山,Mudanchisahn,,,,, +C0R850,林邊,Linbian,,,,, +C0R860,鼻頭,Bitou,,,,, +C0R870,興海,Singhai,,,,, +C0R880,後壁湖,Houbihu,,,,, +C0R890,山海,Shanhai,,,,, +C0R900,竹坑,Jhukeng,,,,, +C0R910,下寮,Sialiao,,,,, +C0R920,塭仔,Wunzai,,,,, +C0R930,萬丹,Wandan,,,,, +C0R940,加祿堂,Jialutang,,,,, +C0R950,萬隆國小,Wanlongguoxiao,,,,, +C0R960,內埔,Neipu,,,,, +C0S660,下馬,Xiama,,,,, +C0S690,太麻里,Taimali,,,,, +C0S700,知本,Jhihben,,,,, +C0S710,鹿野,Luye,,,,, +C0S730,綠島,Ludao,,,,, +C0S740,池上,Chihshang,,,,, +C0S750,向陽,Siangyang,,,,, +C0S760,紅石,Hongshih,,,,, +C0S770,大溪山,Dasishan,,,,, +C0S790,金崙,Jinlun,,,,, +C0S810,東河,Donghe,,,,, +C0S830,長濱,Changbin,,,,, +C0S840,南田,Nantian,,,,, +C0S890,關山,Guanshan,,,,, +C0S900,蘭嶼高中,Lanyu High School,,,,, +C0S910,蘭嶼燈塔,Lanyu Lighthouse,,,,, +C0S920,金峰嘉蘭,Jialan Jinfeng,,,,, +C0S930,延平,Yanping,,,,, +C0S940,石寧山,Shiningshan,,,,, +C0S950,七塊厝,Qikuaicuo,,,,, +C0S960,香蘭,Xianglan,,,,, +C0S970,加津林,Jiajinlin,,,,, +C0S980,勝林山,Shenglinshan,,,,, +C0S990,山豬窟,Shanzhuku,,,,, +C0SA00,歷坵,Liqiu,,,,, +C0SA10,檳榔四格山,Binlangsigeshan,,,,, +C0SA20,金崙山,Jinlunshan,,,,, +C0SA30,都歷,Duli,,,,, +C0SA40,瑞和,Ruihe,,,,, +C0SA60,知本(水試所),Zhiben (FRI),,,,, +C0SA80,土坂,Tuban,,,,, +C0SA90,達仁林場,Darenlinchang,,,,, +C0SB10,美和,Meihe,,,,, +C0SB20,富岡,Fugang,,,,, +C0SB30,新蘭,Dulan Fire Brigade,,,,, +C0SB40,興隆, Xinglong,,,,, +C0SB50,叭嗡嗡,Baweng,,,,, +C0SB60,白守蓮,Baishoulian,,,,, +C0SB70,小港漁港,Xiaogang Fishing Harbor,,,,, +C0SB80,長濱漁港,Changbin Fishing Harbor,,,,, +C0T790,大禹嶺,Dayuling,,,,, +C0T820,天祥,Tianxiang,,,,, +C0T870,鯉魚潭,Liyutan,,,,, +C0T900,西林,Xilin,,,,, +C0T960,光復,Guangfu,,,,, +C0T9A0,月眉山,Yuemeishan,,,,, +C0T9B0,水源,Shuiyuan,,,,, +C0T9D0,和中,Hezhong,,,,, +C0T9E0,大坑,Dakeng,,,,, +C0T9F0,水璉,Shuilian,,,,, +C0T9G0,鳳林山,Fenglinshan,,,,, +C0T9H0,加路蘭山,Jialulanshan,,,,, +C0T9I0,豐濱,Fengbin,,,,, +C0T9M0,靜浦,Jingpu,,,,, +C0T9N0,富里,Fuli,,,,, +C0TA10,花蓮漁港,Hualien Fishing Harbor,,,,, +C0TA20,加灣,Jiawan,,,,, +C0TA30,鹽寮,Yanliao,,,,, +C0TA40,秀林,Xiulin,,,,, +C0TA50,和仁,Heren,,,,, +C0TA80,立霧山,Liwushan,,,,, +C0U520,雙連埤,Shuanglianpi,,,,, +C0U600,礁溪,Chiaoshi,,,,, +C0U650,玉蘭,Yulan,,,,, +C0U710,太平山,Taipingshan,,,,, +C0U720,南山,Nanshan,,,,, +C0U750,龜山島,Gueishandao,,,,, +C0U760,東澳,Dong-Ao,,,,, +C0U770,南澳,Nanao,,,,, +C0U780,五結,Wujie,,,,, +C0U860,頭城,Toucheng,,,,, +C0U870,大礁溪,Dajiaoxi,,,,, +C0U880,北關,Beiguan,,,,, +C0U890,三星,Sanxing,,,,, +C0U900,內城,Neicheng,,,,, +C0U910,冬山,Dongshan,,,,, +C0U940,羅東,Luodong,,,,, +C0U950,鶯子嶺,Yingziling,,,,, +C0U960,翠峰湖,Cuifenghu,,,,, +C0U970,大福,Dafu,,,,, +C0U980,坪林石牌,Shipai Pinglin,,,,, +C0U990,員山,Yuanshan,,,,, +C0UA00,土場,Tuchang,,,,, +C0UA10,鴛鴦湖,Yuanyanghu,,,,, +C0UA20,多加屯,Duojiatun,,,,, +C0UA30,白嶺,Bailing,,,,, +C0UA40,西德山,Xideshan,,,,, +C0UA50,西帽山,Ximaoshan,,,,, +C0UA60,樟樹山,Zhangshushan,,,,, +C0UA70,桃源谷,Taoyuangu,,,,, +C0UA80,大溪漁港,Dasi Fishing Harbor,,,,, +C0UA90,石城,Shihcheng,,,,, +C0UB00,淡江大學蘭陽校園,Tamkang Lanyang Campus,,,,, +C0UB10,蘇澳,Suao,,,,, +C0UB20,壯圍,Jhuangwei,,,,, +C0UB60,明池,Mingchr,,,,, +C0UB70,太平山中間站,Jhongjian,,,,, +C0UB80,翠峰林道6K,Trifong 6k,,,,, +C0UB90,太平山莊,Taipingshan Villa,,,,, +C0V210,復興,Fuxing,,,,, +C0V350,溪埔,Xipu,,,,, +C0V360,內門,Neimen,,,,, +C0V370,古亭坑,Gutingkeng,,,,, +C0V400,阿公店,Agongdian,,,,, +C0V440,鳳山,Fengshan,,,,, +C0V450,鳳森,Fengsen,,,,, +C0V490,新興,Sinsing,,,,, +C0V530,阿蓮,Alian,,,,, +C0V610,梓官,Ziguan,,,,, +C0V620,永安,Yong'An,,,,, +C0V630,茄萣,Qieding,,,,, +C0V640,湖內,Hunei,,,,, +C0V650,彌陀,Mituo,,,,, +C0V660,岡山,Gangshan,,,,, +C0V680,仁武,Renwu,,,,, +C0V690,鼓山,Gushan,,,,, +C0V700,三民,Sanmin,,,,, +C0V710,苓雅,Lingya,,,,, +C0V720,林園,Linyuan,,,,, +C0V730,大寮,Daliao,,,,, +C0V740,旗山,Qishan,,,,, +C0V750,路竹,Luzhu,,,,, +C0V760,橋頭,Qiaotou,,,,, +C0V770,大社,Dashe,,,,, +C0V790,萬山,Wanshan,,,,, +C0V800,六龜,Liugui,,,,, +C0V810,左營,Zuoying,,,,, +C0V820,小林,Xiaolin,,,,, +C0V840,鳳鼻頭,Fongbitou,,,,, +C0V850,蚵仔寮,Kezailiao,,,,, +C0V860,南寮,Nanliao,,,,, +C0V870,文安,Wunan,,,,, +C0V880,興達,Singda,,,,, +C0V890,前鎮,Chian Jhen,,,,, +C0V900,汕尾,Shanwei,,,,, +C0V910,大樹,Dashu,,,,, +C0W110,東莒,Dongju,,,,, +C0W120,西嶼,Xiyu,,,,, +C0W130,花嶼,Huayu,,,,, +C0W140,金沙,Jinsha ,,,,, +C0W150,金寧,Jinning,,,,, +C0W160,烏坵,Wuqiu,,,,, +C0W180,七美,Qimei,,,,, +C0W190,望安,Wangan,,,,, +C0W200,湖西,Husi,,,,, +C0W220,北竿,Beigan,,,,, +C0W240,九宮,Jiugong ,,,,, +C0X050,東河,Donghe,,,,, +C0X060,下營,Xiaying,,,,, +C0X080,佳里,Jiali,,,,, +C0X100,臺南市北區,Beiqu Tainan City,,,,, +C0X110,臺南市南區,Nanqu Tainan City,,,,, +C0X120,麻豆,Madou,,,,, +C0X130,官田,Guantian,,,,, +C0X140,西港,Xigang,,,,, +C0X150,安定,Anding,,,,, +C0X160,仁德,Rende,,,,, +C0X170,關廟,Guanmiao,,,,, +C0X180,山上,Shanshang,,,,, +C0X190,安平,Anping,,,,, +C0X200,左鎮,Zuozhen,,,,, +C0X210,白河,Baihe,,,,, +C0X220,學甲,Xuejia,,,,, +C0X230,鹽水,Yanshui,,,,, +C0X240,關子嶺,Guanziling,,,,, +C0X250,新營,Xinying,,,,, +C0X260,後壁,Houbi,,,,, +C0X280,將軍,Jiangjun,,,,, +C0X290,北門,Beimen,,,,, +C0X300,鹿寮,Luliao,,,,, +C0X320,柳營,Liuying,,,,, +C0Z020,明里,Mingli,,,,, +C0Z050,佳心,Jiaxin,,,,, +C0Z061,玉里,Yuli,,,,, +C0Z070,舞鶴,Wuhe,,,,, +C0Z080,富源,Fuyuan,,,,, +C0Z100,東華,Donghwa,,,,, +C0Z150,吉安光華,Guanghua Ji-An,,,,, +C0Z160,鳳林,Fenglin,,,,, +C0Z170,卓溪,Zhuoxi,,,,, +C0Z180,新城,Xincheng,,,,, +C0Z190,富世,Fushi,,,,, +C0Z200,萬榮,Wanrong,,,,, +C0Z210,瑞穗,Ruisui,,,,, +C0Z220,和平林道,Hepinglindao,,,,, +C0Z230,和平,Heping,,,,, +C0Z250,瑞穗林道,Ruisuilindao,,,,, +C0Z270,蕃薯寮,Fanshuliao,,,,, +C0Z280,德武,Dewu,,,,, +C0Z290,赤柯山,Chikeshan,,,,, +C0Z300,東里,Dongli,,,,, +C0Z310,清水斷崖,Qingshui Cliff,,,,, +C0Z320,清水林道,Qingshuilindao,,,,, +C0Z330,安通山,Antongshan,,,,, +C1A630,下盆,Siapen,,,,, +C1A750,石碇服務區,Shiding Service Area,,,,, +C1A760,坪林交控,Pinglin Traffic Control Center,,,,, +C1A9N0,四十份,Sihshihfen,,,,, +C1AC50,關渡,Guandu,,,,, +C1AI50,國三N016K,Freeway No. 3 - Rain - N016k,,,,, +C1AI60,國一39K邊坡,Freeway No. 1 - Rain – N039k,,,,, +C1C510,水尾,Shueiwei,,,,, +C1D380,新埔,Sinpu,,,,, +C1D400,鳥嘴山,Niaozueishan,,,,, +C1D410,白蘭,Bailan,,,,, +C1D420,太閣南,Taigenan,,,,, +C1D630,飛鳳山,Fei Feng Mountain,,,,, +C1D640,外坪(五指山),Waiping(Wuzhihshan),,,,, +C1E451,象鼻,Xiangbi,,,,, +C1E461,松安,Song-An,,,,, +C1E480,鳳美,Fongmei,,,,, +C1E511,新開,Xinkai,,,,, +C1E601,南勢,Nanshi,,,,, +C1E670,南礦,Nankuang,,,,, +C1E681,南勢山,Nanshishan,,,,, +C1E691,南湖,Nanhu,,,,, +C1E701,八卦,Bagua,,,,, +C1E711,馬拉邦山,Malabangshan,,,,, +C1E721,泰安,Tai-An,,,,, +C1E770,公館,Gongguan,,,,, +C1E890,國三N149K,Freeway No. 1 - Rain – N149k,,,,, +C1E900,國一N128K,Freeway No. 1 - Rain – N128k,,,,, +C1F871,上谷關,Shangguguan,,,,, +C1F891,稍來,Shaolai,,,,, +C1F911,新伯公,Xinbogong,,,,, +C1F941,雪嶺,Xueling,,,,, +C1F9B1,桐林,Tonglin,,,,, +C1F9C1,白冷,Baileng,,,,, +C1F9D1,白毛台,Baimaotai,,,,, +C1F9E1,龍安,Long-An,,,,, +C1F9F1,伯公龍,Bogonglong,,,,, +C1F9G1,慶福山,Cingfushan,,,,, +C1F9J1,清水林,Qingshuilin,,,,, +C1F9W0,德基,Deji,,,,, +C1G691,下水埔,Xiashuipu,,,,, +C1G9D0,國一S218K,Freeway No. 1 - Rain – S218k,,,,, +C1H000,翠峰,Cuifeng,,,,, +C1H840,國三N238K,Freeway No. 3 - Rain –N238k,,,,, +C1H900,清流,Qingliu,,,,, +C1H920,長豐,Changfeng,,,,, +C1H941,雙冬,Shuangdong,,,,, +C1H971,六分寮,Liufenliao,,,,, +C1H9B1,阿眉,Amei,,,,, +C1I020,萬大,Wanda,,,,, +C1I030,武界,Wujie,,,,, +C1I050,丹大,Danda,,,,, +C1I070,和社,Heshe,,,,, +C1I101,溪頭,Xitou,,,,, +C1I121,大鞍,Da-An,,,,, +C1I131,桶頭,Tongtou,,,,, +C1I140,卡奈托灣,Kanaituowan,,,,, +C1I150,青雲,Qingyun,,,,, +C1I201,中心崙,Zhongxinlun,,,,, +C1I211,蘆竹湳,Luzhunan,,,,, +C1I220,樟湖,Zhanghu,,,,, +C1I230,九份二山,Jiufen'Ershan,,,,, +C1I240,外大坪,Waidaping,,,,, +C1I250,鯉潭,Litan,,,,, +C1I260,北坑,Beikeng,,,,, +C1I280,埔中,Puzhong,,,,, +C1I290,豐丘,Fengqiu,,,,, +C1I310,西巒,Xiluan,,,,, +C1I320,奧萬大,Aowanda,,,,, +C1I330,楓樹林,Fengshulin,,,,, +C1I340,新興橋,Xinxingqiao,,,,, +C1I400,凌霄,Lingxiao,,,,, +C1I430,翠華,Cuihua,,,,, +C1I440,新高口,Xingaokou,,,,, +C1I450,望鄉山,Wangxiangshan,,,,, +C1I470,杉林溪,Shanlinxi,,,,, +C1I500,大尖山,Dajianshan,,,,, +C1I510,線浸林道,Xianjinlindao,,,,, +C1I550,國六W023K,Freeway No. 6 - Rain – W023k,,,,, +C1K540,口湖,Kouhu,,,,, +C1M390,龍美,Longmei,,,,, +C1M400,菜瓜坪,Caiguaping,,,,, +C1M480,獨立山,Dulishan,,,,, +C1M600,頭凍,Toudong,,,,, +C1M610,石磐龍,Shipanlong,,,,, +C1M640,十字,Shizi,,,,, +C1M870,國三N285K,Freeway No. 3 - Rain –N285k,,,,, +C1N001,沙崙,Shalun,,,,, +C1O850,環湖,Huanhu,,,,, +C1O870,大棟山,Dadongshan,,,,, +C1O880,關山,Guanshan,,,,, +C1O921,楠西,Nanxi,,,,, +C1O940,東山服務區,Dongshan Service Area,,,,, +C1R110,口社,Gusia,,,,, +C1R120,上德文,Shangdewun,,,,, +C1R250,力里,Lili,,,,, +C1R290,石門山,Shihmenshan,,,,, +C1R610,西大武山,Xidawushan,,,,, +C1R630,龍泉,Longquan,,,,, +C1S670,摩天,Motian,,,,, +C1S800,華源,Huayuan,,,,, +C1S820,金峰,Jinfeng,,,,, +C1S850,豐南,Funan,,,,, +C1S860,利嘉,Lichai,,,,, +C1S870,南美山,Nanmaisan,,,,, +C1S880,壽卡,Shouka,,,,, +C1SA50,利嘉林道,Lijialindao,,,,, +C1SA70,都蘭,Dulan,,,,, +C1T800,洛韶,Luoshao,,,,, +C1T810,慈恩,Ci-En,,,,, +C1T830,布洛灣,Buluowan,,,,, +C1T920,中興,Zhongxing,,,,, +C1T940,大觀,Daguan,,,,, +C1T950,太安,Tai-An,,,,, +C1T970,大農,Danong,,,,, +C1T980,龍澗,Longjian,,,,, +C1T990,高寮,Gaoliao,,,,, +C1TA00,太魯閣,Taroko,,,,, +C1U501,牛鬥,Nioudou,,,,, +C1U670,寒溪,Hanxi,,,,, +C1U840,東澳嶺,Dongaoling,,,,, +C1U850,觀音海岸,Guanyin Coast,,,,, +C1U920,思源,Siyuan,,,,, +C1U930,粉鳥林,Fenniaolin,,,,, +C1V160,達卡努瓦,Dakanuwa,,,,, +C1V170,排雲,Paiyun,,,,, +C1V190,南天池,Nantianchi,,,,, +C1V200,梅山,Meishan,,,,, +C1V220,小關山,Xiaoguanshan,,,,, +C1V231,高中,Gaozhong,,,,, +C1V300,御油山,Yuyoushan,,,,, +C1V340,大津,Dajin,,,,, +C1V390,尖山,Jianshan,,,,, +C1V570,吉東,Jiadong,,,,, +C1V580,溪南(特生中心),Xinan,,,,, +C1V590,新發,Xinfa,,,,, +C1V600,藤枝,Tengzhi,,,,, +C1V780,多納林道,Duonalindao,,,,, +C1V830,國三S383K,Freeway No. 3 - Rain – S383k,,,,, +C1X040,東原,Dongyuan,,,,, +C1Z030,紅葉,Hongye,,,,, +C1Z040,立山,Lishan,,,,, +C1Z110,三棧,Sanzhan,,,,, +C1Z120,壽豐,Shoufeng,,,,, +C1Z130,銅門,Tongmen,,,,, +C1Z140,荖溪,Laoxi,,,,, +C1Z240,中平林道,Zhongpinglindao,,,,, \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..fb725e606 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +/.github/ @exptechtw/dpip-developers + +/lib/app/ @kamiya10 +/lib/models/ @kamiya10 +/lib/core/service.dart @kamiya10 +/tools/update_translations.sh @kamiya10 diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 699ab307f..4954ac06f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -41,22 +41,36 @@ jobs: with: path: ~/.pub-cache key: ubuntu-pub-${{ hashFiles('**/pubspec.lock') }} - restore-keys: | - ubuntu-pub- + restore-keys: ubuntu-pub- - name: Cache build_runner (Optional) uses: actions/cache@v3 with: path: .dart_tool/build - key: ubuntu-build-runner-${{ hashFiles('**/*.dart') }} - restore-keys: | - ubuntu-build-runner- + key: ubuntu-build-runner-${{ hashFiles('lib/api/model/**/*.dart') }} + restore-keys: ubuntu-build-runner- + + - name: Cache Gradle + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ubuntu-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: ubuntu-gradle- + + - name: Cache CMake + uses: actions/cache@v3 + with: + path: /usr/local/lib/android/sdk/cmake + key: ubuntu-android-cmake + restore-keys: ubuntu-android-cmake- - name: Install dependencies run: flutter pub get - name: Prebuild with build_runner - run: dart run build_runner build --delete-conflicting-outputs + run: dart run build_runner build - name: Build apk run: | diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index e0df4aeae..bbf64ee53 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -31,26 +31,24 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Cache Flutter SDK - uses: actions/cache@v3 - with: - path: ~/.pub-cache - key: macos-pub-${{ hashFiles('**/pubspec.lock') }} - restore-keys: | - macos-pub- - - name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} + - name: Cache Pub Packages + uses: actions/cache@v3 + with: + path: ~/.pub-cache + key: macos-pub-${{ hashFiles('**/pubspec.lock') }} + restore-keys: macos-pub- + - name: Cache build_runner (Optional) uses: actions/cache@v3 with: path: .dart_tool/build - key: macos-build-runner-${{ hashFiles('**/*.dart') }} - restore-keys: | - macos-build-runner- + key: macos-build-runner-${{ hashFiles('lib/api/model/**/*.dart') }} + restore-keys: macos-build-runner- - name: Cache CocoaPods Pods uses: actions/cache@v3 @@ -75,7 +73,7 @@ jobs: pod install - name: Prebuild with build_runner - run: dart run build_runner build --delete-conflicting-outputs + run: dart run build_runner build - name: Build iOS App and IPA run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 660f89ca5..14cfce922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ ## [未發布] +### 新增 + +- 氣象類別圖例 +- 地圖頁面-氣象站顯示參數 + +### 更改 + +- 贊助頁面邏輯。 +- 事件時間點順序和時間軸線。 + +### 修正 + +- 強震監視器顯示時間 +- 雷達迴波 被 世界圖層 覆蓋 + ## [3.0.014] - 2025-07-23 ### 新增 @@ -175,9 +190,9 @@ ## [3.0.001] - 2025-05-01 -[未發布]: https://github.com/exptechtw/dpip/compare/v3.0.014...HEAD +[未發布]: https://github.com/exptechtw/dpip/compare/v3.0.0...HEAD [3.0.014]: https://github.com/exptechtw/dpip/compare/v3.0.013(2)...v3.0.014 -[3.0.013]: https://github.com/exptechtw/dpip/compare/v3.0.012...v3.0.013(2) +[3.0.013]: https://github.com/exptechtw/dpip/compare/v3.0.012(1)...v3.0.013(2) [3.0.012]: https://github.com/exptechtw/dpip/compare/v3.0.011...v3.0.012(1) [3.0.011]: https://github.com/exptechtw/dpip/compare/v3.0.010...v3.0.011 [3.0.010]: https://github.com/exptechtw/dpip/compare/v3.0.009...v3.0.010 diff --git a/README.md b/README.md index 2b11f6c9a..b4c1203cb 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Crowdin Localization Greater Good GitHub License -website +website TREM Discord @@ -86,10 +86,10 @@ DPIP 支援多語言,我們正在 Crowdin 平台上進行翻譯。如果你願 - _\*可選\*_ [**Git**](https://git-scm.com/): 用於複製存儲庫 ```console -Flutter 3.33.0-0.2.pre • channel beta • https://github.com/flutter/flutter.git -Framework • revision 1db45f7408 • 2025-05-29 10:05:06 -0700 -Engine • revision 308a517184 • 2025-05-23 15:32:17 -0700 -Tools • Dart 3.9.0 (build 3.9.0-100.2.beta) • DevTools 2.46.0 +Flutter 3.35.1 • channel stable • https://github.com/flutter/flutter.git +Framework • revision 20f8274939 • 2025-08-14 10:53:09 -0700 +Engine • hash 6cd51c08a88e7bbe848a762c20ad3ecb8b063c0e • 2025-08-13 23:35:25.000Z +Tools • Dart 3.9.0 • DevTools 2.48.0 ``` ### 建置步驟 diff --git a/android/app/build.gradle b/android/app/build.gradle index 71d19e43b..b332b9f2c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -48,8 +48,8 @@ android { defaultConfig { applicationId "com.exptech.dpip" minSdkVersion 26 - targetSdkVersion 35 - versionCode 300010000 + targetSdkVersion 36 + versionCode 300100101 versionName flutterVersionName multiDexEnabled true } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0ed01c6a7..fc7f27a2e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + @@ -8,6 +7,7 @@ + diff --git a/assets/location.json b/assets/location.json index bcd89f005..514fdf932 100644 --- a/assets/location.json +++ b/assets/location.json @@ -1 +1 @@ -{"100":{"city":"臺北市","town":"中正區","lat":25.0443212,"lng":121.5247613},"103":{"city":"臺北市","town":"大同區","lat":25.0661934,"lng":121.515268},"104":{"city":"臺北市","town":"中山區","lat":25.0642771,"lng":121.5335776},"105":{"city":"臺北市","town":"松山區","lat":25.049847,"lng":121.577241},"106":{"city":"臺北市","town":"大安區","lat":25.02642,"lng":121.534511},"108":{"city":"臺北市","town":"萬華區","lat":25.034839,"lng":121.4997957},"110":{"city":"臺北市","town":"信義區","lat":25.0331574,"lng":121.5668777},"111":{"city":"臺北市","town":"士林區","lat":25.0927548,"lng":121.519565},"112":{"city":"臺北市","town":"北投區","lat":25.1323666,"lng":121.5029268},"114":{"city":"臺北市","town":"內湖區","lat":25.06929,"lng":121.588949},"115":{"city":"臺北市","town":"南港區","lat":25.0547059,"lng":121.6066929},"116":{"city":"臺北市","town":"文山區","lat":24.98964,"lng":121.5700826},"200":{"city":"基隆市","town":"仁愛區","lat":25.125069,"lng":121.736754},"201":{"city":"基隆市","town":"信義區","lat":25.1294717,"lng":121.7512671},"202":{"city":"基隆市","town":"中正區","lat":25.1407924,"lng":121.7592534},"203":{"city":"基隆市","town":"中山區","lat":25.152899,"lng":121.729552},"204":{"city":"基隆市","town":"安樂區","lat":25.121176,"lng":121.7230804},"205":{"city":"基隆市","town":"暖暖區","lat":25.1001834,"lng":121.735933},"206":{"city":"基隆市","town":"七堵區","lat":25.097653,"lng":121.7165013},"207":{"city":"新北市","town":"萬里區","lat":25.178066,"lng":121.689548},"208":{"city":"新北市","town":"金山區","lat":25.222241,"lng":121.636629},"209":{"city":"連江縣","town":"南竿鄉","lat":26.1529312,"lng":119.9387995},"210":{"city":"連江縣","town":"北竿鄉","lat":26.223938,"lng":119.997139},"211":{"city":"連江縣","town":"莒光鄉","lat":25.9687384,"lng":119.9369689},"212":{"city":"連江縣","town":"東引鄉","lat":26.3672636,"lng":120.4898789},"220":{"city":"新北市","town":"板橋區","lat":25.0096156,"lng":121.4592358},"221":{"city":"新北市","town":"汐止區","lat":25.064261,"lng":121.65869},"222":{"city":"新北市","town":"深坑區","lat":25.0025007,"lng":121.615944},"223":{"city":"新北市","town":"石碇區","lat":24.9914859,"lng":121.6579019},"224":{"city":"新北市","town":"瑞芳區","lat":25.1087635,"lng":121.8098935},"226":{"city":"新北市","town":"平溪區","lat":25.026689,"lng":121.73819},"227":{"city":"新北市","town":"雙溪區","lat":25.0337322,"lng":121.8657341},"228":{"city":"新北市","town":"貢寮區","lat":25.021812,"lng":121.910293},"231":{"city":"新北市","town":"新店區","lat":24.9749713,"lng":121.5431673},"232":{"city":"新北市","town":"坪林區","lat":24.9361367,"lng":121.7117653},"233":{"city":"新北市","town":"烏來區","lat":24.8717802,"lng":121.5478634},"234":{"city":"新北市","town":"永和區","lat":25.0091768,"lng":121.5202731},"235":{"city":"新北市","town":"中和區","lat":24.9985208,"lng":121.5007413},"236":{"city":"新北市","town":"土城區","lat":24.9723361,"lng":121.4429389},"237":{"city":"新北市","town":"三峽區","lat":24.9341863,"lng":121.369083},"238":{"city":"新北市","town":"樹林區","lat":24.9899673,"lng":121.4246321},"239":{"city":"新北市","town":"鶯歌區","lat":24.9560294,"lng":121.3544312},"241":{"city":"新北市","town":"三重區","lat":25.0607692,"lng":121.4884178},"242":{"city":"新北市","town":"新莊區","lat":25.035976,"lng":121.450478},"243":{"city":"新北市","town":"泰山區","lat":25.059291,"lng":121.431495},"244":{"city":"新北市","town":"林口區","lat":25.0768252,"lng":121.3886134},"247":{"city":"新北市","town":"蘆洲區","lat":25.0847112,"lng":121.4737354},"248":{"city":"新北市","town":"五股區","lat":25.0830393,"lng":121.4380781},"249":{"city":"新北市","town":"八里區","lat":25.1537592,"lng":121.4064305},"251":{"city":"新北市","town":"淡水區","lat":25.1696463,"lng":121.4409722},"252":{"city":"新北市","town":"三芝區","lat":25.257748,"lng":121.5009345},"253":{"city":"新北市","town":"石門區","lat":25.291248,"lng":121.567631},"260":{"city":"宜蘭縣","town":"宜蘭市","lat":24.7520373,"lng":121.7531493},"261":{"city":"宜蘭縣","town":"頭城鎮","lat":24.8548387,"lng":121.8213189},"262":{"city":"宜蘭縣","town":"礁溪鄉","lat":24.8234257,"lng":121.7711725},"263":{"city":"宜蘭縣","town":"壯圍鄉","lat":24.746832,"lng":121.785759},"264":{"city":"宜蘭縣","town":"員山鄉","lat":24.7433944,"lng":121.7232538},"265":{"city":"宜蘭縣","town":"羅東鎮","lat":24.6769245,"lng":121.7669529},"266":{"city":"宜蘭縣","town":"三星鄉","lat":24.665483,"lng":121.654047},"267":{"city":"宜蘭縣","town":"大同鄉","lat":24.677412,"lng":121.6090927},"268":{"city":"宜蘭縣","town":"五結鄉","lat":24.684772,"lng":121.7982898},"269":{"city":"宜蘭縣","town":"冬山鄉","lat":24.634338,"lng":121.792851},"270":{"city":"宜蘭縣","town":"蘇澳鎮","lat":24.594315,"lng":121.8421903},"272":{"city":"宜蘭縣","town":"南澳鄉","lat":24.465996,"lng":121.803714},"300":{"city":"新竹市","town":"北區","lat":24.8163726,"lng":120.9703141},"301":{"city":"新竹市","town":"東區","lat":24.8051881,"lng":120.9732327},"309":{"city":"新竹市","town":"香山區","lat":24.7940445,"lng":120.9422678},"302":{"city":"新竹縣","town":"竹北市","lat":24.8395807,"lng":121.0040235},"303":{"city":"新竹縣","town":"湖口鄉","lat":24.9010068,"lng":121.0478749},"304":{"city":"新竹縣","town":"新豐鄉","lat":24.9007026,"lng":120.9852313},"305":{"city":"新竹縣","town":"新埔鎮","lat":24.8256201,"lng":121.0740799},"306":{"city":"新竹縣","town":"關西鎮","lat":24.7922806,"lng":121.1759547},"307":{"city":"新竹縣","town":"芎林鄉","lat":24.773309,"lng":121.081855},"308":{"city":"新竹縣","town":"寶山鄉","lat":24.7654715,"lng":120.9913066},"310":{"city":"新竹縣","town":"竹東鎮","lat":24.7366942,"lng":121.0916513},"311":{"city":"新竹縣","town":"五峰鄉","lat":24.6320786,"lng":121.119596},"312":{"city":"新竹縣","town":"橫山鄉","lat":24.7167807,"lng":121.1414985},"313":{"city":"新竹縣","town":"尖石鄉","lat":24.705004,"lng":121.2020864},"314":{"city":"新竹縣","town":"北埔鄉","lat":24.7019901,"lng":121.0563354},"315":{"city":"新竹縣","town":"峨眉鄉","lat":24.6887921,"lng":121.0195946},"320":{"city":"桃園市","town":"中壢區","lat":24.9656124,"lng":121.2249927},"324":{"city":"桃園市","town":"平鎮區","lat":24.9456694,"lng":121.2181884},"325":{"city":"桃園市","town":"龍潭區","lat":24.8704855,"lng":121.2224472},"326":{"city":"桃園市","town":"楊梅區","lat":24.9128508,"lng":121.1444587},"327":{"city":"桃園市","town":"新屋區","lat":24.9725439,"lng":121.105533},"328":{"city":"桃園市","town":"觀音區","lat":25.0276516,"lng":121.0836028},"330":{"city":"桃園市","town":"桃園區","lat":24.993919,"lng":121.3016657},"333":{"city":"桃園市","town":"龜山區","lat":24.9925139,"lng":121.337824},"334":{"city":"桃園市","town":"八德區","lat":24.9289862,"lng":121.2846406},"335":{"city":"桃園市","town":"大溪區","lat":24.880548,"lng":121.287142},"336":{"city":"桃園市","town":"復興區","lat":24.8147989,"lng":121.3511305},"337":{"city":"桃園市","town":"大園區","lat":25.0638556,"lng":121.1954603},"338":{"city":"桃園市","town":"蘆竹區","lat":25.046925,"lng":121.295077},"350":{"city":"苗栗縣","town":"竹南鎮","lat":24.6838448,"lng":120.8733503},"351":{"city":"苗栗縣","town":"頭份市","lat":24.6865276,"lng":120.9132454},"352":{"city":"苗栗縣","town":"三灣鄉","lat":24.6531425,"lng":120.9566265},"353":{"city":"苗栗縣","town":"南庄鄉","lat":24.5970648,"lng":121.000339},"354":{"city":"苗栗縣","town":"獅潭鄉","lat":24.539419,"lng":120.920496},"356":{"city":"苗栗縣","town":"後龍鎮","lat":24.613682,"lng":120.792046},"357":{"city":"苗栗縣","town":"通霄鎮","lat":24.4912805,"lng":120.684249},"358":{"city":"苗栗縣","town":"苑裡鎮","lat":24.4396522,"lng":120.653261},"360":{"city":"苗栗縣","town":"苗栗市","lat":24.5616772,"lng":120.8190175},"361":{"city":"苗栗縣","town":"造橋鄉","lat":24.638552,"lng":120.8651632},"362":{"city":"苗栗縣","town":"頭屋鄉","lat":24.5778158,"lng":120.8511057},"363":{"city":"苗栗縣","town":"公館鄉","lat":24.5058646,"lng":120.8284935},"364":{"city":"苗栗縣","town":"大湖鄉","lat":24.4234081,"lng":120.8661781},"365":{"city":"苗栗縣","town":"泰安鄉","lat":24.4471976,"lng":120.9081718},"366":{"city":"苗栗縣","town":"銅鑼鄉","lat":24.4870514,"lng":120.7878718},"367":{"city":"苗栗縣","town":"三義鄉","lat":24.4129179,"lng":120.7702392},"368":{"city":"苗栗縣","town":"西湖鄉","lat":24.5567613,"lng":120.7570814},"369":{"city":"苗栗縣","town":"卓蘭鎮","lat":24.3130501,"lng":120.8245152},"400":{"city":"臺中市","town":"中區","lat":24.1439458,"lng":120.6794414},"401":{"city":"臺中市","town":"東區","lat":24.1366469,"lng":120.7037332},"402":{"city":"臺中市","town":"南區","lat":24.1171412,"lng":120.6635905},"403":{"city":"臺中市","town":"西區","lat":24.1413252,"lng":120.6710753},"404":{"city":"臺中市","town":"北區","lat":24.1658534,"lng":120.6822936},"406":{"city":"臺中市","town":"北屯區","lat":24.1826848,"lng":120.686403},"407":{"city":"臺中市","town":"西屯區","lat":24.1658213,"lng":120.6336717},"408":{"city":"臺中市","town":"南屯區","lat":24.1345298,"lng":120.6442903},"411":{"city":"臺中市","town":"太平區","lat":24.1266572,"lng":120.7185562},"412":{"city":"臺中市","town":"大里區","lat":24.0994693,"lng":120.6778413},"413":{"city":"臺中市","town":"霧峰區","lat":24.0613153,"lng":120.7000868},"414":{"city":"臺中市","town":"烏日區","lat":24.104605,"lng":120.6238467},"420":{"city":"臺中市","town":"豐原區","lat":24.2419087,"lng":120.7181281},"421":{"city":"臺中市","town":"后里區","lat":24.3049377,"lng":120.7107454},"422":{"city":"臺中市","town":"石岡區","lat":24.274898,"lng":120.7803458},"423":{"city":"臺中市","town":"東勢區","lat":24.2585728,"lng":120.8279546},"424":{"city":"臺中市","town":"和平區","lat":24.1752225,"lng":120.8835809},"426":{"city":"臺中市","town":"新社區","lat":24.233957,"lng":120.809416},"427":{"city":"臺中市","town":"潭子區","lat":24.2031708,"lng":120.7228978},"428":{"city":"臺中市","town":"大雅區","lat":24.2291463,"lng":120.6478436},"429":{"city":"臺中市","town":"神岡區","lat":24.2579749,"lng":120.6614216},"432":{"city":"臺中市","town":"大肚區","lat":24.1511295,"lng":120.5457643},"433":{"city":"臺中市","town":"沙鹿區","lat":24.2333313,"lng":120.566317},"434":{"city":"臺中市","town":"龍井區","lat":24.1924488,"lng":120.5457999},"435":{"city":"臺中市","town":"梧棲區","lat":24.2549063,"lng":120.5317002},"436":{"city":"臺中市","town":"清水區","lat":24.2681562,"lng":120.559717},"437":{"city":"臺中市","town":"大甲區","lat":24.349083,"lng":120.622468},"438":{"city":"臺中市","town":"外埔區","lat":24.3321248,"lng":120.654334},"439":{"city":"臺中市","town":"大安區","lat":24.346126,"lng":120.5866075},"500":{"city":"彰化縣","town":"彰化市","lat":24.0809056,"lng":120.5422565},"502":{"city":"彰化縣","town":"芬園鄉","lat":24.013628,"lng":120.628964},"503":{"city":"彰化縣","town":"花壇鄉","lat":24.0296582,"lng":120.5382578},"504":{"city":"彰化縣","town":"秀水鄉","lat":24.035321,"lng":120.5028098},"505":{"city":"彰化縣","town":"鹿港鎮","lat":24.0572566,"lng":120.4350548},"506":{"city":"彰化縣","town":"福興鄉","lat":24.0478713,"lng":120.4439546},"507":{"city":"彰化縣","town":"線西鄉","lat":24.1306678,"lng":120.470656},"508":{"city":"彰化縣","town":"和美鎮","lat":24.1085584,"lng":120.4941497},"509":{"city":"彰化縣","town":"伸港鄉","lat":24.1596067,"lng":120.4861141},"510":{"city":"彰化縣","town":"員林市","lat":23.9589162,"lng":120.5743943},"511":{"city":"彰化縣","town":"社頭鄉","lat":23.8968186,"lng":120.5858074},"512":{"city":"彰化縣","town":"永靖鄉","lat":23.9245962,"lng":120.5477204},"513":{"city":"彰化縣","town":"埔心鄉","lat":23.952988,"lng":120.54354},"514":{"city":"彰化縣","town":"溪湖鎮","lat":23.9664245,"lng":120.4832787},"515":{"city":"彰化縣","town":"大村鄉","lat":23.9934239,"lng":120.547268},"516":{"city":"彰化縣","town":"埔鹽鄉","lat":24.000442,"lng":120.4636578},"520":{"city":"彰化縣","town":"田中鎮","lat":23.8614831,"lng":120.5809585},"521":{"city":"彰化縣","town":"北斗鎮","lat":23.8713826,"lng":120.5218625},"522":{"city":"彰化縣","town":"田尾鄉","lat":23.8922407,"lng":120.5259709},"523":{"city":"彰化縣","town":"埤頭鄉","lat":23.8914618,"lng":120.4621725},"524":{"city":"彰化縣","town":"溪州鄉","lat":23.8516188,"lng":120.498976},"525":{"city":"彰化縣","town":"竹塘鄉","lat":23.8605045,"lng":120.4277961},"526":{"city":"彰化縣","town":"二林鎮","lat":23.8998045,"lng":120.3742654},"527":{"city":"彰化縣","town":"大城鄉","lat":23.852314,"lng":120.3208972},"528":{"city":"彰化縣","town":"芳苑鄉","lat":23.924354,"lng":120.320389},"530":{"city":"彰化縣","town":"二水鄉","lat":23.8066858,"lng":120.6190203},"540":{"city":"南投縣","town":"南投市","lat":23.9116414,"lng":120.6874199},"541":{"city":"南投縣","town":"中寮鄉","lat":23.8790067,"lng":120.7660301},"542":{"city":"南投縣","town":"草屯鎮","lat":23.9736845,"lng":120.6802819},"544":{"city":"南投縣","town":"國姓鄉","lat":24.040019,"lng":120.8575192},"545":{"city":"南投縣","town":"埔里鎮","lat":23.9665377,"lng":120.9691809},"546":{"city":"南投縣","town":"仁愛鄉","lat":24.021544,"lng":121.1320616},"551":{"city":"南投縣","town":"名間鄉","lat":23.8382161,"lng":120.702985},"552":{"city":"南投縣","town":"集集鎮","lat":23.8283683,"lng":120.7864885},"553":{"city":"南投縣","town":"水里鄉","lat":23.8113991,"lng":120.8560852},"555":{"city":"南投縣","town":"魚池鄉","lat":23.8957849,"lng":120.9356849},"556":{"city":"南投縣","town":"信義鄉","lat":23.696797,"lng":120.854557},"557":{"city":"南投縣","town":"竹山鎮","lat":23.7578635,"lng":120.6716995},"558":{"city":"南投縣","town":"鹿谷鄉","lat":23.7458415,"lng":120.7534428},"600":{"city":"嘉義市","town":"東區","lat":23.4786578,"lng":120.4534596},"601":{"city":"嘉義市","town":"西區","lat":23.4646967,"lng":120.4352822},"602":{"city":"嘉義縣","town":"番路鄉","lat":23.4644973,"lng":120.554286},"603":{"city":"嘉義縣","town":"梅山鄉","lat":23.5850678,"lng":120.5554676},"604":{"city":"嘉義縣","town":"竹崎鄉","lat":23.5230788,"lng":120.5513988},"605":{"city":"嘉義縣","town":"阿里山鄉","lat":23.4712117,"lng":120.7135217},"606":{"city":"嘉義縣","town":"中埔鄉","lat":23.425139,"lng":120.522952},"607":{"city":"嘉義縣","town":"大埔鄉","lat":23.2986941,"lng":120.5869311},"608":{"city":"嘉義縣","town":"水上鄉","lat":23.428531,"lng":120.398035},"611":{"city":"嘉義縣","town":"鹿草鄉","lat":23.4113835,"lng":120.3082682},"612":{"city":"嘉義縣","town":"太保市","lat":23.458967,"lng":120.3323479},"613":{"city":"嘉義縣","town":"朴子市","lat":23.4575288,"lng":120.2459226},"614":{"city":"嘉義縣","town":"東石鄉","lat":23.4587147,"lng":120.1537883},"615":{"city":"嘉義縣","town":"六腳鄉","lat":23.4940922,"lng":120.2907962},"616":{"city":"嘉義縣","town":"新港鄉","lat":23.5519744,"lng":120.3478039},"621":{"city":"嘉義縣","town":"民雄鄉","lat":23.5516417,"lng":120.4283616},"622":{"city":"嘉義縣","town":"大林鎮","lat":23.603931,"lng":120.471178},"623":{"city":"嘉義縣","town":"溪口鄉","lat":23.6025304,"lng":120.392323},"624":{"city":"嘉義縣","town":"義竹鄉","lat":23.3361064,"lng":120.2430475},"625":{"city":"嘉義縣","town":"布袋鎮","lat":23.3781734,"lng":120.1669564},"630":{"city":"雲林縣","town":"斗南鎮","lat":23.680105,"lng":120.47772},"631":{"city":"雲林縣","town":"大埤鄉","lat":23.6460343,"lng":120.4314818},"632":{"city":"雲林縣","town":"虎尾鎮","lat":23.7083539,"lng":120.4451923},"633":{"city":"雲林縣","town":"土庫鎮","lat":23.6820621,"lng":120.3899062},"634":{"city":"雲林縣","town":"褒忠鄉","lat":23.691007,"lng":120.3037335},"635":{"city":"雲林縣","town":"東勢鄉","lat":23.6753034,"lng":120.2525936},"636":{"city":"雲林縣","town":"臺西鄉","lat":23.700477,"lng":120.1957632},"637":{"city":"雲林縣","town":"崙背鄉","lat":23.7619087,"lng":120.3591424},"638":{"city":"雲林縣","town":"麥寮鄉","lat":23.7539853,"lng":120.2513078},"640":{"city":"雲林縣","town":"斗六市","lat":23.6971143,"lng":120.5269987},"643":{"city":"雲林縣","town":"林內鄉","lat":23.7562156,"lng":120.6129427},"646":{"city":"雲林縣","town":"古坑鄉","lat":23.6426312,"lng":120.5619595},"647":{"city":"雲林縣","town":"莿桐鄉","lat":23.7610077,"lng":120.5025072},"648":{"city":"雲林縣","town":"西螺鎮","lat":23.7977736,"lng":120.465685},"649":{"city":"雲林縣","town":"二崙鄉","lat":23.7711012,"lng":120.4129596},"651":{"city":"雲林縣","town":"北港鎮","lat":23.5759236,"lng":120.302446},"652":{"city":"雲林縣","town":"水林鄉","lat":23.5727035,"lng":120.2459507},"653":{"city":"雲林縣","town":"口湖鄉","lat":23.5827378,"lng":120.1858552},"654":{"city":"雲林縣","town":"四湖鄉","lat":23.6378317,"lng":120.2242949},"655":{"city":"雲林縣","town":"元長鄉","lat":23.6497447,"lng":120.3148349},"700":{"city":"臺南市","town":"中西區","lat":22.9922364,"lng":120.2056571},"701":{"city":"臺南市","town":"東區","lat":22.9802421,"lng":120.224004},"702":{"city":"臺南市","town":"南區","lat":22.9611326,"lng":120.1885687},"704":{"city":"臺南市","town":"北區","lat":22.9997522,"lng":120.2030341},"708":{"city":"臺南市","town":"安平區","lat":22.9945789,"lng":120.1688523},"709":{"city":"臺南市","town":"安南區","lat":23.0472321,"lng":120.184714},"710":{"city":"臺南市","town":"永康區","lat":23.0260699,"lng":120.2570647},"711":{"city":"臺南市","town":"歸仁區","lat":22.967286,"lng":120.2940045},"712":{"city":"臺南市","town":"新化區","lat":23.0385411,"lng":120.310896},"713":{"city":"臺南市","town":"左鎮區","lat":23.0567783,"lng":120.408708},"714":{"city":"臺南市","town":"玉井區","lat":23.1237866,"lng":120.4601109},"715":{"city":"臺南市","town":"楠西區","lat":23.174143,"lng":120.486337},"716":{"city":"臺南市","town":"南化區","lat":23.042988,"lng":120.477816},"717":{"city":"臺南市","town":"仁德區","lat":22.97243,"lng":120.251685},"718":{"city":"臺南市","town":"關廟區","lat":22.9630039,"lng":120.3278144},"719":{"city":"臺南市","town":"龍崎區","lat":22.9632926,"lng":120.3649712},"720":{"city":"臺南市","town":"官田區","lat":23.1930442,"lng":120.3154967},"721":{"city":"臺南市","town":"麻豆區","lat":23.1849449,"lng":120.2584456},"722":{"city":"臺南市","town":"佳里區","lat":23.1652648,"lng":120.1770306},"723":{"city":"臺南市","town":"西港區","lat":23.1229825,"lng":120.203413},"724":{"city":"臺南市","town":"七股區","lat":23.1403809,"lng":120.1391359},"725":{"city":"臺南市","town":"將軍區","lat":23.19905,"lng":120.158702},"726":{"city":"臺南市","town":"學甲區","lat":23.2304835,"lng":120.1822926},"727":{"city":"臺南市","town":"北門區","lat":23.267723,"lng":120.125445},"730":{"city":"臺南市","town":"新營區","lat":23.3101426,"lng":120.3167031},"731":{"city":"臺南市","town":"後壁區","lat":23.3659836,"lng":120.3619362},"732":{"city":"臺南市","town":"白河區","lat":23.3512886,"lng":120.415752},"733":{"city":"臺南市","town":"東山區","lat":23.3261625,"lng":120.4045009},"734":{"city":"臺南市","town":"六甲區","lat":23.2318098,"lng":120.3474201},"735":{"city":"臺南市","town":"下營區","lat":23.2356921,"lng":120.2643838},"736":{"city":"臺南市","town":"柳營區","lat":23.278395,"lng":120.311673},"737":{"city":"臺南市","town":"鹽水區","lat":23.320027,"lng":120.266097},"741":{"city":"臺南市","town":"善化區","lat":23.1324288,"lng":120.2967849},"742":{"city":"臺南市","town":"大內區","lat":23.1192073,"lng":120.3568212},"743":{"city":"臺南市","town":"山上區","lat":23.1036173,"lng":120.3526487},"744":{"city":"臺南市","town":"新市區","lat":23.0789967,"lng":120.2951827},"745":{"city":"臺南市","town":"安定區","lat":23.121593,"lng":120.237118},"800":{"city":"高雄市","town":"新興區","lat":22.6310347,"lng":120.3101095},"801":{"city":"高雄市","town":"前金區","lat":22.6275276,"lng":120.2942181},"802":{"city":"高雄市","town":"苓雅區","lat":22.621759,"lng":120.312194},"803":{"city":"高雄市","town":"鹽埕區","lat":22.6247166,"lng":120.2868098},"804":{"city":"高雄市","town":"鼓山區","lat":22.636776,"lng":120.2809626},"805":{"city":"高雄市","town":"旗津區","lat":22.5900263,"lng":120.28471},"806":{"city":"高雄市","town":"前鎮區","lat":22.5865658,"lng":120.318307},"807":{"city":"高雄市","town":"三民區","lat":22.647684,"lng":120.299851},"811":{"city":"高雄市","town":"楠梓區","lat":22.7283655,"lng":120.3263681},"812":{"city":"高雄市","town":"小港區","lat":22.5652134,"lng":120.3380368},"813":{"city":"高雄市","town":"左營區","lat":22.6899834,"lng":120.2950135},"814":{"city":"高雄市","town":"仁武區","lat":22.7013806,"lng":120.3479837},"815":{"city":"高雄市","town":"大社區","lat":22.730156,"lng":120.346671},"820":{"city":"高雄市","town":"岡山區","lat":22.7974649,"lng":120.2950724},"821":{"city":"高雄市","town":"路竹區","lat":22.8547435,"lng":120.2592442},"822":{"city":"高雄市","town":"阿蓮區","lat":22.8832024,"lng":120.3274131},"823":{"city":"高雄市","town":"田寮區","lat":22.8698825,"lng":120.3594334},"824":{"city":"高雄市","town":"燕巢區","lat":22.7881575,"lng":120.3619685},"825":{"city":"高雄市","town":"橋頭區","lat":22.757591,"lng":120.305809},"826":{"city":"高雄市","town":"梓官區","lat":22.7606303,"lng":120.2671523},"827":{"city":"高雄市","town":"彌陀區","lat":22.7814893,"lng":120.2507011},"828":{"city":"高雄市","town":"永安區","lat":22.818298,"lng":120.224189},"829":{"city":"高雄市","town":"湖內區","lat":22.9083136,"lng":120.211713},"830":{"city":"高雄市","town":"鳳山區","lat":22.627075,"lng":120.362525},"831":{"city":"高雄市","town":"大寮區","lat":22.6055196,"lng":120.3956199},"832":{"city":"高雄市","town":"林園區","lat":22.5129453,"lng":120.3946805},"833":{"city":"高雄市","town":"鳥松區","lat":22.6598339,"lng":120.364363},"840":{"city":"高雄市","town":"大樹區","lat":22.6839054,"lng":120.4143416},"842":{"city":"高雄市","town":"旗山區","lat":22.888642,"lng":120.48349},"843":{"city":"高雄市","town":"美濃區","lat":22.8947952,"lng":120.5419493},"844":{"city":"高雄市","town":"六龜區","lat":22.9984391,"lng":120.6327082},"845":{"city":"高雄市","town":"內門區","lat":22.9428391,"lng":120.462606},"846":{"city":"高雄市","town":"杉林區","lat":22.9717391,"lng":120.540058},"847":{"city":"高雄市","town":"甲仙區","lat":23.0839058,"lng":120.587695},"848":{"city":"高雄市","town":"桃源區","lat":23.1592827,"lng":120.7641372},"849":{"city":"高雄市","town":"那瑪夏區","lat":23.277092,"lng":120.720243},"851":{"city":"高雄市","town":"茂林區","lat":22.886187,"lng":120.663266},"852":{"city":"高雄市","town":"茄萣區","lat":22.9065231,"lng":120.1824729},"880":{"city":"澎湖縣","town":"馬公市","lat":23.566159,"lng":119.578692},"881":{"city":"澎湖縣","town":"西嶼鄉","lat":23.601088,"lng":119.5069847},"882":{"city":"澎湖縣","town":"望安鄉","lat":23.3576577,"lng":119.500894},"883":{"city":"澎湖縣","town":"七美鄉","lat":23.2067107,"lng":119.4244825},"884":{"city":"澎湖縣","town":"白沙鄉","lat":23.666538,"lng":119.598639},"885":{"city":"澎湖縣","town":"湖西鄉","lat":23.584072,"lng":119.6528318},"890":{"city":"金門縣","town":"金沙鎮","lat":24.488898,"lng":118.413132},"891":{"city":"金門縣","town":"金湖鎮","lat":24.4414641,"lng":118.4171018},"892":{"city":"金門縣","town":"金寧鄉","lat":24.450966,"lng":118.334887},"893":{"city":"金門縣","town":"金城鎮","lat":24.432824,"lng":118.320697},"894":{"city":"金門縣","town":"烈嶼鄉","lat":24.4295409,"lng":118.2445892},"896":{"city":"金門縣","town":"烏坵鄉","lat":24.9887062,"lng":119.4531826},"900":{"city":"屏東縣","town":"屏東市","lat":22.662498,"lng":120.4914295},"901":{"city":"屏東縣","town":"三地門鄉","lat":22.7162015,"lng":120.6541301},"902":{"city":"屏東縣","town":"霧臺鄉","lat":22.7490518,"lng":120.7282593},"903":{"city":"屏東縣","town":"瑪家鄉","lat":22.7086763,"lng":120.6494041},"904":{"city":"屏東縣","town":"九如鄉","lat":22.740429,"lng":120.4903298},"905":{"city":"屏東縣","town":"里港鄉","lat":22.7792625,"lng":120.4944974},"906":{"city":"屏東縣","town":"高樹鄉","lat":22.8267314,"lng":120.600241},"907":{"city":"屏東縣","town":"鹽埔鄉","lat":22.7543743,"lng":120.5727019},"908":{"city":"屏東縣","town":"長治鄉","lat":22.676538,"lng":120.5272963},"909":{"city":"屏東縣","town":"麟洛鄉","lat":22.6506473,"lng":120.5272056},"911":{"city":"屏東縣","town":"竹田鄉","lat":22.584724,"lng":120.543981},"912":{"city":"屏東縣","town":"內埔鄉","lat":22.6120045,"lng":120.5668293},"913":{"city":"屏東縣","town":"萬丹鄉","lat":22.5894894,"lng":120.4850182},"920":{"city":"屏東縣","town":"潮州鎮","lat":22.549845,"lng":120.5429633},"921":{"city":"屏東縣","town":"泰武鄉","lat":22.5919045,"lng":120.6319498},"922":{"city":"屏東縣","town":"來義鄉","lat":22.5261844,"lng":120.6315782},"923":{"city":"屏東縣","town":"萬巒鄉","lat":22.5726416,"lng":120.567841},"924":{"city":"屏東縣","town":"崁頂鄉","lat":22.5147343,"lng":120.5140493},"925":{"city":"屏東縣","town":"新埤鄉","lat":22.4701881,"lng":120.5498736},"926":{"city":"屏東縣","town":"南州鄉","lat":22.490404,"lng":120.509879},"927":{"city":"屏東縣","town":"林邊鄉","lat":22.431504,"lng":120.5097562},"928":{"city":"屏東縣","town":"東港鎮","lat":22.4666854,"lng":120.454361},"929":{"city":"屏東縣","town":"琉球鄉","lat":22.348635,"lng":120.3827309},"931":{"city":"屏東縣","town":"佳冬鄉","lat":22.419209,"lng":120.5524196},"932":{"city":"屏東縣","town":"新園鄉","lat":22.5438351,"lng":120.4614914},"940":{"city":"屏東縣","town":"枋寮鄉","lat":22.3655097,"lng":120.5934906},"941":{"city":"屏東縣","town":"枋山鄉","lat":22.2639616,"lng":120.6524803},"942":{"city":"屏東縣","town":"春日鄉","lat":22.3710005,"lng":120.6290908},"943":{"city":"屏東縣","town":"獅子鄉","lat":22.201775,"lng":120.705438},"944":{"city":"屏東縣","town":"車城鄉","lat":22.0739409,"lng":120.714276},"945":{"city":"屏東縣","town":"牡丹鄉","lat":22.1261502,"lng":120.7743059},"946":{"city":"屏東縣","town":"恆春鎮","lat":22.0037401,"lng":120.7472461},"947":{"city":"屏東縣","town":"滿州鄉","lat":22.020813,"lng":120.838632},"950":{"city":"臺東縣","town":"臺東市","lat":22.7548208,"lng":121.1465131},"951":{"city":"臺東縣","town":"綠島鄉","lat":22.6658421,"lng":121.4705314},"952":{"city":"臺東縣","town":"蘭嶼鄉","lat":22.0244984,"lng":121.5560627},"953":{"city":"臺東縣","town":"延平鄉","lat":22.9025753,"lng":121.0860671},"954":{"city":"臺東縣","town":"卑南鄉","lat":22.7827393,"lng":121.0870294},"955":{"city":"臺東縣","town":"鹿野鄉","lat":22.9393083,"lng":121.1519859},"956":{"city":"臺東縣","town":"關山鎮","lat":23.0474453,"lng":121.1630554},"957":{"city":"臺東縣","town":"海端鄉","lat":23.102057,"lng":121.176541},"958":{"city":"臺東縣","town":"池上鄉","lat":23.1223101,"lng":121.2151887},"959":{"city":"臺東縣","town":"東河鄉","lat":22.9689404,"lng":121.3028937},"961":{"city":"臺東縣","town":"成功鎮","lat":23.1050697,"lng":121.3808747},"962":{"city":"臺東縣","town":"長濱鄉","lat":23.3149961,"lng":121.4514207},"963":{"city":"臺東縣","town":"太麻里鄉","lat":22.615548,"lng":121.007607},"964":{"city":"臺東縣","town":"金峰鄉","lat":22.5946397,"lng":120.9607096},"965":{"city":"臺東縣","town":"大武鄉","lat":22.340518,"lng":120.890073},"966":{"city":"臺東縣","town":"達仁鄉","lat":22.296818,"lng":120.882973},"970":{"city":"花蓮縣","town":"花蓮市","lat":23.9820651,"lng":121.6067705},"971":{"city":"花蓮縣","town":"新城鄉","lat":24.0392994,"lng":121.6041173},"972":{"city":"花蓮縣","town":"秀林鄉","lat":24.1185835,"lng":121.6248326},"973":{"city":"花蓮縣","town":"吉安鄉","lat":23.9729455,"lng":121.5636438},"974":{"city":"花蓮縣","town":"壽豐鄉","lat":23.8703424,"lng":121.5088259},"975":{"city":"花蓮縣","town":"鳳林鎮","lat":23.7447637,"lng":121.4515822},"976":{"city":"花蓮縣","town":"光復鄉","lat":23.669342,"lng":121.4233065},"977":{"city":"花蓮縣","town":"豐濱鄉","lat":23.6012024,"lng":121.5211488},"978":{"city":"花蓮縣","town":"瑞穗鄉","lat":23.4964553,"lng":121.3757788},"979":{"city":"花蓮縣","town":"萬榮鄉","lat":23.714875,"lng":121.4109617},"981":{"city":"花蓮縣","town":"玉里鎮","lat":23.335527,"lng":121.315197},"982":{"city":"花蓮縣","town":"卓溪鄉","lat":23.346478,"lng":121.303451},"983":{"city":"花蓮縣","town":"富里鄉","lat":23.1794845,"lng":121.250233}} \ No newline at end of file +{"100":{"city":"臺北","town":"中正","lat":25.0443212,"lng":121.5247613,"cityLevel":"市","townLevel":"區"},"103":{"city":"臺北","town":"大同","lat":25.0661934,"lng":121.515268,"cityLevel":"市","townLevel":"區"},"104":{"city":"臺北","town":"中山","lat":25.0642771,"lng":121.5335776,"cityLevel":"市","townLevel":"區"},"105":{"city":"臺北","town":"松山","lat":25.049847,"lng":121.577241,"cityLevel":"市","townLevel":"區"},"106":{"city":"臺北","town":"大安","lat":25.02642,"lng":121.534511,"cityLevel":"市","townLevel":"區"},"108":{"city":"臺北","town":"萬華","lat":25.034839,"lng":121.4997957,"cityLevel":"市","townLevel":"區"},"110":{"city":"臺北","town":"信義","lat":25.0331574,"lng":121.5668777,"cityLevel":"市","townLevel":"區"},"111":{"city":"臺北","town":"士林","lat":25.0927548,"lng":121.519565,"cityLevel":"市","townLevel":"區"},"112":{"city":"臺北","town":"北投","lat":25.1323666,"lng":121.5029268,"cityLevel":"市","townLevel":"區"},"114":{"city":"臺北","town":"內湖","lat":25.06929,"lng":121.588949,"cityLevel":"市","townLevel":"區"},"115":{"city":"臺北","town":"南港","lat":25.0547059,"lng":121.6066929,"cityLevel":"市","townLevel":"區"},"116":{"city":"臺北","town":"文山","lat":24.98964,"lng":121.5700826,"cityLevel":"市","townLevel":"區"},"200":{"city":"基隆","town":"仁愛","lat":25.125069,"lng":121.736754,"cityLevel":"市","townLevel":"區"},"201":{"city":"基隆","town":"信義","lat":25.1294717,"lng":121.7512671,"cityLevel":"市","townLevel":"區"},"202":{"city":"基隆","town":"中正","lat":25.1407924,"lng":121.7592534,"cityLevel":"市","townLevel":"區"},"203":{"city":"基隆","town":"中山","lat":25.152899,"lng":121.729552,"cityLevel":"市","townLevel":"區"},"204":{"city":"基隆","town":"安樂","lat":25.121176,"lng":121.7230804,"cityLevel":"市","townLevel":"區"},"205":{"city":"基隆","town":"暖暖","lat":25.1001834,"lng":121.735933,"cityLevel":"市","townLevel":"區"},"206":{"city":"基隆","town":"七堵","lat":25.097653,"lng":121.7165013,"cityLevel":"市","townLevel":"區"},"207":{"city":"新北","town":"萬里","lat":25.178066,"lng":121.689548,"cityLevel":"市","townLevel":"區"},"208":{"city":"新北","town":"金山","lat":25.222241,"lng":121.636629,"cityLevel":"市","townLevel":"區"},"209":{"city":"連江","town":"南竿","lat":26.1529312,"lng":119.9387995,"cityLevel":"縣","townLevel":"鄉"},"210":{"city":"連江","town":"北竿","lat":26.223938,"lng":119.997139,"cityLevel":"縣","townLevel":"鄉"},"211":{"city":"連江","town":"莒光","lat":25.9687384,"lng":119.9369689,"cityLevel":"縣","townLevel":"鄉"},"212":{"city":"連江","town":"東引","lat":26.3672636,"lng":120.4898789,"cityLevel":"縣","townLevel":"鄉"},"220":{"city":"新北","town":"板橋","lat":25.0096156,"lng":121.4592358,"cityLevel":"市","townLevel":"區"},"221":{"city":"新北","town":"汐止","lat":25.064261,"lng":121.65869,"cityLevel":"市","townLevel":"區"},"222":{"city":"新北","town":"深坑","lat":25.0025007,"lng":121.615944,"cityLevel":"市","townLevel":"區"},"223":{"city":"新北","town":"石碇","lat":24.9914859,"lng":121.6579019,"cityLevel":"市","townLevel":"區"},"224":{"city":"新北","town":"瑞芳","lat":25.1087635,"lng":121.8098935,"cityLevel":"市","townLevel":"區"},"226":{"city":"新北","town":"平溪","lat":25.026689,"lng":121.73819,"cityLevel":"市","townLevel":"區"},"227":{"city":"新北","town":"雙溪","lat":25.0337322,"lng":121.8657341,"cityLevel":"市","townLevel":"區"},"228":{"city":"新北","town":"貢寮","lat":25.021812,"lng":121.910293,"cityLevel":"市","townLevel":"區"},"231":{"city":"新北","town":"新店","lat":24.9749713,"lng":121.5431673,"cityLevel":"市","townLevel":"區"},"232":{"city":"新北","town":"坪林","lat":24.9361367,"lng":121.7117653,"cityLevel":"市","townLevel":"區"},"233":{"city":"新北","town":"烏來","lat":24.8717802,"lng":121.5478634,"cityLevel":"市","townLevel":"區"},"234":{"city":"新北","town":"永和","lat":25.0091768,"lng":121.5202731,"cityLevel":"市","townLevel":"區"},"235":{"city":"新北","town":"中和","lat":24.9985208,"lng":121.5007413,"cityLevel":"市","townLevel":"區"},"236":{"city":"新北","town":"土城","lat":24.9723361,"lng":121.4429389,"cityLevel":"市","townLevel":"區"},"237":{"city":"新北","town":"三峽","lat":24.9341863,"lng":121.369083,"cityLevel":"市","townLevel":"區"},"238":{"city":"新北","town":"樹林","lat":24.9899673,"lng":121.4246321,"cityLevel":"市","townLevel":"區"},"239":{"city":"新北","town":"鶯歌","lat":24.9560294,"lng":121.3544312,"cityLevel":"市","townLevel":"區"},"241":{"city":"新北","town":"三重","lat":25.0607692,"lng":121.4884178,"cityLevel":"市","townLevel":"區"},"242":{"city":"新北","town":"新莊","lat":25.035976,"lng":121.450478,"cityLevel":"市","townLevel":"區"},"243":{"city":"新北","town":"泰山","lat":25.059291,"lng":121.431495,"cityLevel":"市","townLevel":"區"},"244":{"city":"新北","town":"林口","lat":25.0768252,"lng":121.3886134,"cityLevel":"市","townLevel":"區"},"247":{"city":"新北","town":"蘆洲","lat":25.0847112,"lng":121.4737354,"cityLevel":"市","townLevel":"區"},"248":{"city":"新北","town":"五股","lat":25.0830393,"lng":121.4380781,"cityLevel":"市","townLevel":"區"},"249":{"city":"新北","town":"八里","lat":25.1537592,"lng":121.4064305,"cityLevel":"市","townLevel":"區"},"251":{"city":"新北","town":"淡水","lat":25.1696463,"lng":121.4409722,"cityLevel":"市","townLevel":"區"},"252":{"city":"新北","town":"三芝","lat":25.257748,"lng":121.5009345,"cityLevel":"市","townLevel":"區"},"253":{"city":"新北","town":"石門","lat":25.291248,"lng":121.567631,"cityLevel":"市","townLevel":"區"},"260":{"city":"宜蘭","town":"宜蘭","lat":24.7520373,"lng":121.7531493,"cityLevel":"縣","townLevel":"市"},"261":{"city":"宜蘭","town":"頭城","lat":24.8548387,"lng":121.8213189,"cityLevel":"縣","townLevel":"鎮"},"262":{"city":"宜蘭","town":"礁溪","lat":24.8234257,"lng":121.7711725,"cityLevel":"縣","townLevel":"鄉"},"263":{"city":"宜蘭","town":"壯圍","lat":24.746832,"lng":121.785759,"cityLevel":"縣","townLevel":"鄉"},"264":{"city":"宜蘭","town":"員山","lat":24.7433944,"lng":121.7232538,"cityLevel":"縣","townLevel":"鄉"},"265":{"city":"宜蘭","town":"羅東","lat":24.6769245,"lng":121.7669529,"cityLevel":"縣","townLevel":"鎮"},"266":{"city":"宜蘭","town":"三星","lat":24.665483,"lng":121.654047,"cityLevel":"縣","townLevel":"鄉"},"267":{"city":"宜蘭","town":"大同","lat":24.677412,"lng":121.6090927,"cityLevel":"縣","townLevel":"鄉"},"268":{"city":"宜蘭","town":"五結","lat":24.684772,"lng":121.7982898,"cityLevel":"縣","townLevel":"鄉"},"269":{"city":"宜蘭","town":"冬山","lat":24.634338,"lng":121.792851,"cityLevel":"縣","townLevel":"鄉"},"270":{"city":"宜蘭","town":"蘇澳","lat":24.594315,"lng":121.8421903,"cityLevel":"縣","townLevel":"鎮"},"272":{"city":"宜蘭","town":"南澳","lat":24.465996,"lng":121.803714,"cityLevel":"縣","townLevel":"鄉"},"300":{"city":"新竹","town":"北","lat":24.8163726,"lng":120.9703141,"cityLevel":"市","townLevel":"區"},"301":{"city":"新竹","town":"東","lat":24.8051881,"lng":120.9732327,"cityLevel":"市","townLevel":"區"},"302":{"city":"新竹","town":"竹北","lat":24.8395807,"lng":121.0040235,"cityLevel":"縣","townLevel":"市"},"303":{"city":"新竹","town":"湖口","lat":24.9010068,"lng":121.0478749,"cityLevel":"縣","townLevel":"鄉"},"304":{"city":"新竹","town":"新豐","lat":24.9007026,"lng":120.9852313,"cityLevel":"縣","townLevel":"鄉"},"305":{"city":"新竹","town":"新埔","lat":24.8256201,"lng":121.0740799,"cityLevel":"縣","townLevel":"鎮"},"306":{"city":"新竹","town":"關西","lat":24.7922806,"lng":121.1759547,"cityLevel":"縣","townLevel":"鎮"},"307":{"city":"新竹","town":"芎林","lat":24.773309,"lng":121.081855,"cityLevel":"縣","townLevel":"鄉"},"308":{"city":"新竹","town":"寶山","lat":24.7654715,"lng":120.9913066,"cityLevel":"縣","townLevel":"鄉"},"309":{"city":"新竹","town":"香山","lat":24.7940445,"lng":120.9422678,"cityLevel":"市","townLevel":"區"},"310":{"city":"新竹","town":"竹東","lat":24.7366942,"lng":121.0916513,"cityLevel":"縣","townLevel":"鎮"},"311":{"city":"新竹","town":"五峰","lat":24.6320786,"lng":121.119596,"cityLevel":"縣","townLevel":"鄉"},"312":{"city":"新竹","town":"橫山","lat":24.7167807,"lng":121.1414985,"cityLevel":"縣","townLevel":"鄉"},"313":{"city":"新竹","town":"尖石","lat":24.705004,"lng":121.2020864,"cityLevel":"縣","townLevel":"鄉"},"314":{"city":"新竹","town":"北埔","lat":24.7019901,"lng":121.0563354,"cityLevel":"縣","townLevel":"鄉"},"315":{"city":"新竹","town":"峨眉","lat":24.6887921,"lng":121.0195946,"cityLevel":"縣","townLevel":"鄉"},"320":{"city":"桃園","town":"中壢","lat":24.9656124,"lng":121.2249927,"cityLevel":"市","townLevel":"區"},"324":{"city":"桃園","town":"平鎮","lat":24.9456694,"lng":121.2181884,"cityLevel":"市","townLevel":"區"},"325":{"city":"桃園","town":"龍潭","lat":24.8704855,"lng":121.2224472,"cityLevel":"市","townLevel":"區"},"326":{"city":"桃園","town":"楊梅","lat":24.9128508,"lng":121.1444587,"cityLevel":"市","townLevel":"區"},"327":{"city":"桃園","town":"新屋","lat":24.9725439,"lng":121.105533,"cityLevel":"市","townLevel":"區"},"328":{"city":"桃園","town":"觀音","lat":25.0276516,"lng":121.0836028,"cityLevel":"市","townLevel":"區"},"330":{"city":"桃園","town":"桃園","lat":24.993919,"lng":121.3016657,"cityLevel":"市","townLevel":"區"},"333":{"city":"桃園","town":"龜山","lat":24.9925139,"lng":121.337824,"cityLevel":"市","townLevel":"區"},"334":{"city":"桃園","town":"八德","lat":24.9289862,"lng":121.2846406,"cityLevel":"市","townLevel":"區"},"335":{"city":"桃園","town":"大溪","lat":24.880548,"lng":121.287142,"cityLevel":"市","townLevel":"區"},"336":{"city":"桃園","town":"復興","lat":24.8147989,"lng":121.3511305,"cityLevel":"市","townLevel":"區"},"337":{"city":"桃園","town":"大園","lat":25.0638556,"lng":121.1954603,"cityLevel":"市","townLevel":"區"},"338":{"city":"桃園","town":"蘆竹","lat":25.046925,"lng":121.295077,"cityLevel":"市","townLevel":"區"},"350":{"city":"苗栗","town":"竹南","lat":24.6838448,"lng":120.8733503,"cityLevel":"縣","townLevel":"鎮"},"351":{"city":"苗栗","town":"頭份","lat":24.6865276,"lng":120.9132454,"cityLevel":"縣","townLevel":"市"},"352":{"city":"苗栗","town":"三灣","lat":24.6531425,"lng":120.9566265,"cityLevel":"縣","townLevel":"鄉"},"353":{"city":"苗栗","town":"南庄","lat":24.5970648,"lng":121.000339,"cityLevel":"縣","townLevel":"鄉"},"354":{"city":"苗栗","town":"獅潭","lat":24.539419,"lng":120.920496,"cityLevel":"縣","townLevel":"鄉"},"356":{"city":"苗栗","town":"後龍","lat":24.613682,"lng":120.792046,"cityLevel":"縣","townLevel":"鎮"},"357":{"city":"苗栗","town":"通霄","lat":24.4912805,"lng":120.684249,"cityLevel":"縣","townLevel":"鎮"},"358":{"city":"苗栗","town":"苑裡","lat":24.4396522,"lng":120.653261,"cityLevel":"縣","townLevel":"鎮"},"360":{"city":"苗栗","town":"苗栗","lat":24.5616772,"lng":120.8190175,"cityLevel":"縣","townLevel":"市"},"361":{"city":"苗栗","town":"造橋","lat":24.638552,"lng":120.8651632,"cityLevel":"縣","townLevel":"鄉"},"362":{"city":"苗栗","town":"頭屋","lat":24.5778158,"lng":120.8511057,"cityLevel":"縣","townLevel":"鄉"},"363":{"city":"苗栗","town":"公館","lat":24.5058646,"lng":120.8284935,"cityLevel":"縣","townLevel":"鄉"},"364":{"city":"苗栗","town":"大湖","lat":24.4234081,"lng":120.8661781,"cityLevel":"縣","townLevel":"鄉"},"365":{"city":"苗栗","town":"泰安","lat":24.4471976,"lng":120.9081718,"cityLevel":"縣","townLevel":"鄉"},"366":{"city":"苗栗","town":"銅鑼","lat":24.4870514,"lng":120.7878718,"cityLevel":"縣","townLevel":"鄉"},"367":{"city":"苗栗","town":"三義","lat":24.4129179,"lng":120.7702392,"cityLevel":"縣","townLevel":"鄉"},"368":{"city":"苗栗","town":"西湖","lat":24.5567613,"lng":120.7570814,"cityLevel":"縣","townLevel":"鄉"},"369":{"city":"苗栗","town":"卓蘭","lat":24.3130501,"lng":120.8245152,"cityLevel":"縣","townLevel":"鎮"},"400":{"city":"臺中","town":"中","lat":24.1439458,"lng":120.6794414,"cityLevel":"市","townLevel":"區"},"401":{"city":"臺中","town":"東","lat":24.1366469,"lng":120.7037332,"cityLevel":"市","townLevel":"區"},"402":{"city":"臺中","town":"南","lat":24.1171412,"lng":120.6635905,"cityLevel":"市","townLevel":"區"},"403":{"city":"臺中","town":"西","lat":24.1413252,"lng":120.6710753,"cityLevel":"市","townLevel":"區"},"404":{"city":"臺中","town":"北","lat":24.1658534,"lng":120.6822936,"cityLevel":"市","townLevel":"區"},"406":{"city":"臺中","town":"北屯","lat":24.1826848,"lng":120.686403,"cityLevel":"市","townLevel":"區"},"407":{"city":"臺中","town":"西屯","lat":24.1658213,"lng":120.6336717,"cityLevel":"市","townLevel":"區"},"408":{"city":"臺中","town":"南屯","lat":24.1345298,"lng":120.6442903,"cityLevel":"市","townLevel":"區"},"411":{"city":"臺中","town":"太平","lat":24.1266572,"lng":120.7185562,"cityLevel":"市","townLevel":"區"},"412":{"city":"臺中","town":"大里","lat":24.0994693,"lng":120.6778413,"cityLevel":"市","townLevel":"區"},"413":{"city":"臺中","town":"霧峰","lat":24.0613153,"lng":120.7000868,"cityLevel":"市","townLevel":"區"},"414":{"city":"臺中","town":"烏日","lat":24.104605,"lng":120.6238467,"cityLevel":"市","townLevel":"區"},"420":{"city":"臺中","town":"豐原","lat":24.2419087,"lng":120.7181281,"cityLevel":"市","townLevel":"區"},"421":{"city":"臺中","town":"后里","lat":24.3049377,"lng":120.7107454,"cityLevel":"市","townLevel":"區"},"422":{"city":"臺中","town":"石岡","lat":24.274898,"lng":120.7803458,"cityLevel":"市","townLevel":"區"},"423":{"city":"臺中","town":"東勢","lat":24.2585728,"lng":120.8279546,"cityLevel":"市","townLevel":"區"},"424":{"city":"臺中","town":"和平","lat":24.1752225,"lng":120.8835809,"cityLevel":"市","townLevel":"區"},"426":{"city":"臺中","town":"新社","lat":24.233957,"lng":120.809416,"cityLevel":"市","townLevel":"區"},"427":{"city":"臺中","town":"潭子","lat":24.2031708,"lng":120.7228978,"cityLevel":"市","townLevel":"區"},"428":{"city":"臺中","town":"大雅","lat":24.2291463,"lng":120.6478436,"cityLevel":"市","townLevel":"區"},"429":{"city":"臺中","town":"神岡","lat":24.2579749,"lng":120.6614216,"cityLevel":"市","townLevel":"區"},"432":{"city":"臺中","town":"大肚","lat":24.1511295,"lng":120.5457643,"cityLevel":"市","townLevel":"區"},"433":{"city":"臺中","town":"沙鹿","lat":24.2333313,"lng":120.566317,"cityLevel":"市","townLevel":"區"},"434":{"city":"臺中","town":"龍井","lat":24.1924488,"lng":120.5457999,"cityLevel":"市","townLevel":"區"},"435":{"city":"臺中","town":"梧棲","lat":24.2549063,"lng":120.5317002,"cityLevel":"市","townLevel":"區"},"436":{"city":"臺中","town":"清水","lat":24.2681562,"lng":120.559717,"cityLevel":"市","townLevel":"區"},"437":{"city":"臺中","town":"大甲","lat":24.349083,"lng":120.622468,"cityLevel":"市","townLevel":"區"},"438":{"city":"臺中","town":"外埔","lat":24.3321248,"lng":120.654334,"cityLevel":"市","townLevel":"區"},"439":{"city":"臺中","town":"大安","lat":24.346126,"lng":120.5866075,"cityLevel":"市","townLevel":"區"},"500":{"city":"彰化","town":"彰化","lat":24.0809056,"lng":120.5422565,"cityLevel":"縣","townLevel":"市"},"502":{"city":"彰化","town":"芬園","lat":24.013628,"lng":120.628964,"cityLevel":"縣","townLevel":"鄉"},"503":{"city":"彰化","town":"花壇","lat":24.0296582,"lng":120.5382578,"cityLevel":"縣","townLevel":"鄉"},"504":{"city":"彰化","town":"秀水","lat":24.035321,"lng":120.5028098,"cityLevel":"縣","townLevel":"鄉"},"505":{"city":"彰化","town":"鹿港","lat":24.0572566,"lng":120.4350548,"cityLevel":"縣","townLevel":"鎮"},"506":{"city":"彰化","town":"福興","lat":24.0478713,"lng":120.4439546,"cityLevel":"縣","townLevel":"鄉"},"507":{"city":"彰化","town":"線西","lat":24.1306678,"lng":120.470656,"cityLevel":"縣","townLevel":"鄉"},"508":{"city":"彰化","town":"和美","lat":24.1085584,"lng":120.4941497,"cityLevel":"縣","townLevel":"鎮"},"509":{"city":"彰化","town":"伸港","lat":24.1596067,"lng":120.4861141,"cityLevel":"縣","townLevel":"鄉"},"510":{"city":"彰化","town":"員林","lat":23.9589162,"lng":120.5743943,"cityLevel":"縣","townLevel":"市"},"511":{"city":"彰化","town":"社頭","lat":23.8968186,"lng":120.5858074,"cityLevel":"縣","townLevel":"鄉"},"512":{"city":"彰化","town":"永靖","lat":23.9245962,"lng":120.5477204,"cityLevel":"縣","townLevel":"鄉"},"513":{"city":"彰化","town":"埔心","lat":23.952988,"lng":120.54354,"cityLevel":"縣","townLevel":"鄉"},"514":{"city":"彰化","town":"溪湖","lat":23.9664245,"lng":120.4832787,"cityLevel":"縣","townLevel":"鎮"},"515":{"city":"彰化","town":"大村","lat":23.9934239,"lng":120.547268,"cityLevel":"縣","townLevel":"鄉"},"516":{"city":"彰化","town":"埔鹽","lat":24.000442,"lng":120.4636578,"cityLevel":"縣","townLevel":"鄉"},"520":{"city":"彰化","town":"田中","lat":23.8614831,"lng":120.5809585,"cityLevel":"縣","townLevel":"鎮"},"521":{"city":"彰化","town":"北斗","lat":23.8713826,"lng":120.5218625,"cityLevel":"縣","townLevel":"鎮"},"522":{"city":"彰化","town":"田尾","lat":23.8922407,"lng":120.5259709,"cityLevel":"縣","townLevel":"鄉"},"523":{"city":"彰化","town":"埤頭","lat":23.8914618,"lng":120.4621725,"cityLevel":"縣","townLevel":"鄉"},"524":{"city":"彰化","town":"溪州","lat":23.8516188,"lng":120.498976,"cityLevel":"縣","townLevel":"鄉"},"525":{"city":"彰化","town":"竹塘","lat":23.8605045,"lng":120.4277961,"cityLevel":"縣","townLevel":"鄉"},"526":{"city":"彰化","town":"二林","lat":23.8998045,"lng":120.3742654,"cityLevel":"縣","townLevel":"鎮"},"527":{"city":"彰化","town":"大城","lat":23.852314,"lng":120.3208972,"cityLevel":"縣","townLevel":"鄉"},"528":{"city":"彰化","town":"芳苑","lat":23.924354,"lng":120.320389,"cityLevel":"縣","townLevel":"鄉"},"530":{"city":"彰化","town":"二水","lat":23.8066858,"lng":120.6190203,"cityLevel":"縣","townLevel":"鄉"},"540":{"city":"南投","town":"南投","lat":23.9116414,"lng":120.6874199,"cityLevel":"縣","townLevel":"市"},"541":{"city":"南投","town":"中寮","lat":23.8790067,"lng":120.7660301,"cityLevel":"縣","townLevel":"鄉"},"542":{"city":"南投","town":"草屯","lat":23.9736845,"lng":120.6802819,"cityLevel":"縣","townLevel":"鎮"},"544":{"city":"南投","town":"國姓","lat":24.040019,"lng":120.8575192,"cityLevel":"縣","townLevel":"鄉"},"545":{"city":"南投","town":"埔里","lat":23.9665377,"lng":120.9691809,"cityLevel":"縣","townLevel":"鎮"},"546":{"city":"南投","town":"仁愛","lat":24.021544,"lng":121.1320616,"cityLevel":"縣","townLevel":"鄉"},"551":{"city":"南投","town":"名間","lat":23.8382161,"lng":120.702985,"cityLevel":"縣","townLevel":"鄉"},"552":{"city":"南投","town":"集集","lat":23.8283683,"lng":120.7864885,"cityLevel":"縣","townLevel":"鎮"},"553":{"city":"南投","town":"水里","lat":23.8113991,"lng":120.8560852,"cityLevel":"縣","townLevel":"鄉"},"555":{"city":"南投","town":"魚池","lat":23.8957849,"lng":120.9356849,"cityLevel":"縣","townLevel":"鄉"},"556":{"city":"南投","town":"信義","lat":23.696797,"lng":120.854557,"cityLevel":"縣","townLevel":"鄉"},"557":{"city":"南投","town":"竹山","lat":23.7578635,"lng":120.6716995,"cityLevel":"縣","townLevel":"鎮"},"558":{"city":"南投","town":"鹿谷","lat":23.7458415,"lng":120.7534428,"cityLevel":"縣","townLevel":"鄉"},"600":{"city":"嘉義","town":"東","lat":23.4786578,"lng":120.4534596,"cityLevel":"市","townLevel":"區"},"601":{"city":"嘉義","town":"西","lat":23.4646967,"lng":120.4352822,"cityLevel":"市","townLevel":"區"},"602":{"city":"嘉義","town":"番路","lat":23.4644973,"lng":120.554286,"cityLevel":"縣","townLevel":"鄉"},"603":{"city":"嘉義","town":"梅山","lat":23.5850678,"lng":120.5554676,"cityLevel":"縣","townLevel":"鄉"},"604":{"city":"嘉義","town":"竹崎","lat":23.5230788,"lng":120.5513988,"cityLevel":"縣","townLevel":"鄉"},"605":{"city":"嘉義","town":"阿里山","lat":23.4712117,"lng":120.7135217,"cityLevel":"縣","townLevel":"鄉"},"606":{"city":"嘉義","town":"中埔","lat":23.425139,"lng":120.522952,"cityLevel":"縣","townLevel":"鄉"},"607":{"city":"嘉義","town":"大埔","lat":23.2986941,"lng":120.5869311,"cityLevel":"縣","townLevel":"鄉"},"608":{"city":"嘉義","town":"水上","lat":23.428531,"lng":120.398035,"cityLevel":"縣","townLevel":"鄉"},"611":{"city":"嘉義","town":"鹿草","lat":23.4113835,"lng":120.3082682,"cityLevel":"縣","townLevel":"鄉"},"612":{"city":"嘉義","town":"太保","lat":23.458967,"lng":120.3323479,"cityLevel":"縣","townLevel":"市"},"613":{"city":"嘉義","town":"朴子","lat":23.4575288,"lng":120.2459226,"cityLevel":"縣","townLevel":"市"},"614":{"city":"嘉義","town":"東石","lat":23.4587147,"lng":120.1537883,"cityLevel":"縣","townLevel":"鄉"},"615":{"city":"嘉義","town":"六腳","lat":23.4940922,"lng":120.2907962,"cityLevel":"縣","townLevel":"鄉"},"616":{"city":"嘉義","town":"新港","lat":23.5519744,"lng":120.3478039,"cityLevel":"縣","townLevel":"鄉"},"621":{"city":"嘉義","town":"民雄","lat":23.5516417,"lng":120.4283616,"cityLevel":"縣","townLevel":"鄉"},"622":{"city":"嘉義","town":"大林","lat":23.603931,"lng":120.471178,"cityLevel":"縣","townLevel":"鎮"},"623":{"city":"嘉義","town":"溪口","lat":23.6025304,"lng":120.392323,"cityLevel":"縣","townLevel":"鄉"},"624":{"city":"嘉義","town":"義竹","lat":23.3361064,"lng":120.2430475,"cityLevel":"縣","townLevel":"鄉"},"625":{"city":"嘉義","town":"布袋","lat":23.3781734,"lng":120.1669564,"cityLevel":"縣","townLevel":"鎮"},"630":{"city":"雲林","town":"斗南","lat":23.680105,"lng":120.47772,"cityLevel":"縣","townLevel":"鎮"},"631":{"city":"雲林","town":"大埤","lat":23.6460343,"lng":120.4314818,"cityLevel":"縣","townLevel":"鄉"},"632":{"city":"雲林","town":"虎尾","lat":23.7083539,"lng":120.4451923,"cityLevel":"縣","townLevel":"鎮"},"633":{"city":"雲林","town":"土庫","lat":23.6820621,"lng":120.3899062,"cityLevel":"縣","townLevel":"鎮"},"634":{"city":"雲林","town":"褒忠","lat":23.691007,"lng":120.3037335,"cityLevel":"縣","townLevel":"鄉"},"635":{"city":"雲林","town":"東勢","lat":23.6753034,"lng":120.2525936,"cityLevel":"縣","townLevel":"鄉"},"636":{"city":"雲林","town":"臺西","lat":23.700477,"lng":120.1957632,"cityLevel":"縣","townLevel":"鄉"},"637":{"city":"雲林","town":"崙背","lat":23.7619087,"lng":120.3591424,"cityLevel":"縣","townLevel":"鄉"},"638":{"city":"雲林","town":"麥寮","lat":23.7539853,"lng":120.2513078,"cityLevel":"縣","townLevel":"鄉"},"640":{"city":"雲林","town":"斗六","lat":23.6971143,"lng":120.5269987,"cityLevel":"縣","townLevel":"市"},"643":{"city":"雲林","town":"林內","lat":23.7562156,"lng":120.6129427,"cityLevel":"縣","townLevel":"鄉"},"646":{"city":"雲林","town":"古坑","lat":23.6426312,"lng":120.5619595,"cityLevel":"縣","townLevel":"鄉"},"647":{"city":"雲林","town":"莿桐","lat":23.7610077,"lng":120.5025072,"cityLevel":"縣","townLevel":"鄉"},"648":{"city":"雲林","town":"西螺","lat":23.7977736,"lng":120.465685,"cityLevel":"縣","townLevel":"鎮"},"649":{"city":"雲林","town":"二崙","lat":23.7711012,"lng":120.4129596,"cityLevel":"縣","townLevel":"鄉"},"651":{"city":"雲林","town":"北港","lat":23.5759236,"lng":120.302446,"cityLevel":"縣","townLevel":"鎮"},"652":{"city":"雲林","town":"水林","lat":23.5727035,"lng":120.2459507,"cityLevel":"縣","townLevel":"鄉"},"653":{"city":"雲林","town":"口湖","lat":23.5827378,"lng":120.1858552,"cityLevel":"縣","townLevel":"鄉"},"654":{"city":"雲林","town":"四湖","lat":23.6378317,"lng":120.2242949,"cityLevel":"縣","townLevel":"鄉"},"655":{"city":"雲林","town":"元長","lat":23.6497447,"lng":120.3148349,"cityLevel":"縣","townLevel":"鄉"},"700":{"city":"臺南","town":"中西","lat":22.9922364,"lng":120.2056571,"cityLevel":"市","townLevel":"區"},"701":{"city":"臺南","town":"東","lat":22.9802421,"lng":120.224004,"cityLevel":"市","townLevel":"區"},"702":{"city":"臺南","town":"南","lat":22.9611326,"lng":120.1885687,"cityLevel":"市","townLevel":"區"},"704":{"city":"臺南","town":"北","lat":22.9997522,"lng":120.2030341,"cityLevel":"市","townLevel":"區"},"708":{"city":"臺南","town":"安平","lat":22.9945789,"lng":120.1688523,"cityLevel":"市","townLevel":"區"},"709":{"city":"臺南","town":"安南","lat":23.0472321,"lng":120.184714,"cityLevel":"市","townLevel":"區"},"710":{"city":"臺南","town":"永康","lat":23.0260699,"lng":120.2570647,"cityLevel":"市","townLevel":"區"},"711":{"city":"臺南","town":"歸仁","lat":22.967286,"lng":120.2940045,"cityLevel":"市","townLevel":"區"},"712":{"city":"臺南","town":"新化","lat":23.0385411,"lng":120.310896,"cityLevel":"市","townLevel":"區"},"713":{"city":"臺南","town":"左鎮","lat":23.0567783,"lng":120.408708,"cityLevel":"市","townLevel":"區"},"714":{"city":"臺南","town":"玉井","lat":23.1237866,"lng":120.4601109,"cityLevel":"市","townLevel":"區"},"715":{"city":"臺南","town":"楠西","lat":23.174143,"lng":120.486337,"cityLevel":"市","townLevel":"區"},"716":{"city":"臺南","town":"南化","lat":23.042988,"lng":120.477816,"cityLevel":"市","townLevel":"區"},"717":{"city":"臺南","town":"仁德","lat":22.97243,"lng":120.251685,"cityLevel":"市","townLevel":"區"},"718":{"city":"臺南","town":"關廟","lat":22.9630039,"lng":120.3278144,"cityLevel":"市","townLevel":"區"},"719":{"city":"臺南","town":"龍崎","lat":22.9632926,"lng":120.3649712,"cityLevel":"市","townLevel":"區"},"720":{"city":"臺南","town":"官田","lat":23.1930442,"lng":120.3154967,"cityLevel":"市","townLevel":"區"},"721":{"city":"臺南","town":"麻豆","lat":23.1849449,"lng":120.2584456,"cityLevel":"市","townLevel":"區"},"722":{"city":"臺南","town":"佳里","lat":23.1652648,"lng":120.1770306,"cityLevel":"市","townLevel":"區"},"723":{"city":"臺南","town":"西港","lat":23.1229825,"lng":120.203413,"cityLevel":"市","townLevel":"區"},"724":{"city":"臺南","town":"七股","lat":23.1403809,"lng":120.1391359,"cityLevel":"市","townLevel":"區"},"725":{"city":"臺南","town":"將軍","lat":23.19905,"lng":120.158702,"cityLevel":"市","townLevel":"區"},"726":{"city":"臺南","town":"學甲","lat":23.2304835,"lng":120.1822926,"cityLevel":"市","townLevel":"區"},"727":{"city":"臺南","town":"北門","lat":23.267723,"lng":120.125445,"cityLevel":"市","townLevel":"區"},"730":{"city":"臺南","town":"新營","lat":23.3101426,"lng":120.3167031,"cityLevel":"市","townLevel":"區"},"731":{"city":"臺南","town":"後壁","lat":23.3659836,"lng":120.3619362,"cityLevel":"市","townLevel":"區"},"732":{"city":"臺南","town":"白河","lat":23.3512886,"lng":120.415752,"cityLevel":"市","townLevel":"區"},"733":{"city":"臺南","town":"東山","lat":23.3261625,"lng":120.4045009,"cityLevel":"市","townLevel":"區"},"734":{"city":"臺南","town":"六甲","lat":23.2318098,"lng":120.3474201,"cityLevel":"市","townLevel":"區"},"735":{"city":"臺南","town":"下營","lat":23.2356921,"lng":120.2643838,"cityLevel":"市","townLevel":"區"},"736":{"city":"臺南","town":"柳營","lat":23.278395,"lng":120.311673,"cityLevel":"市","townLevel":"區"},"737":{"city":"臺南","town":"鹽水","lat":23.320027,"lng":120.266097,"cityLevel":"市","townLevel":"區"},"741":{"city":"臺南","town":"善化","lat":23.1324288,"lng":120.2967849,"cityLevel":"市","townLevel":"區"},"742":{"city":"臺南","town":"大內","lat":23.1192073,"lng":120.3568212,"cityLevel":"市","townLevel":"區"},"743":{"city":"臺南","town":"山上","lat":23.1036173,"lng":120.3526487,"cityLevel":"市","townLevel":"區"},"744":{"city":"臺南","town":"新市","lat":23.0789967,"lng":120.2951827,"cityLevel":"市","townLevel":"區"},"745":{"city":"臺南","town":"安定","lat":23.121593,"lng":120.237118,"cityLevel":"市","townLevel":"區"},"800":{"city":"高雄","town":"新興","lat":22.6310347,"lng":120.3101095,"cityLevel":"市","townLevel":"區"},"801":{"city":"高雄","town":"前金","lat":22.6275276,"lng":120.2942181,"cityLevel":"市","townLevel":"區"},"802":{"city":"高雄","town":"苓雅","lat":22.621759,"lng":120.312194,"cityLevel":"市","townLevel":"區"},"803":{"city":"高雄","town":"鹽埕","lat":22.6247166,"lng":120.2868098,"cityLevel":"市","townLevel":"區"},"804":{"city":"高雄","town":"鼓山","lat":22.636776,"lng":120.2809626,"cityLevel":"市","townLevel":"區"},"805":{"city":"高雄","town":"旗津","lat":22.5900263,"lng":120.28471,"cityLevel":"市","townLevel":"區"},"806":{"city":"高雄","town":"前鎮","lat":22.5865658,"lng":120.318307,"cityLevel":"市","townLevel":"區"},"807":{"city":"高雄","town":"三民","lat":22.647684,"lng":120.299851,"cityLevel":"市","townLevel":"區"},"811":{"city":"高雄","town":"楠梓","lat":22.7283655,"lng":120.3263681,"cityLevel":"市","townLevel":"區"},"812":{"city":"高雄","town":"小港","lat":22.5652134,"lng":120.3380368,"cityLevel":"市","townLevel":"區"},"813":{"city":"高雄","town":"左營","lat":22.6899834,"lng":120.2950135,"cityLevel":"市","townLevel":"區"},"814":{"city":"高雄","town":"仁武","lat":22.7013806,"lng":120.3479837,"cityLevel":"市","townLevel":"區"},"815":{"city":"高雄","town":"大社","lat":22.730156,"lng":120.346671,"cityLevel":"市","townLevel":"區"},"820":{"city":"高雄","town":"岡山","lat":22.7974649,"lng":120.2950724,"cityLevel":"市","townLevel":"區"},"821":{"city":"高雄","town":"路竹","lat":22.8547435,"lng":120.2592442,"cityLevel":"市","townLevel":"區"},"822":{"city":"高雄","town":"阿蓮","lat":22.8832024,"lng":120.3274131,"cityLevel":"市","townLevel":"區"},"823":{"city":"高雄","town":"田寮","lat":22.8698825,"lng":120.3594334,"cityLevel":"市","townLevel":"區"},"824":{"city":"高雄","town":"燕巢","lat":22.7881575,"lng":120.3619685,"cityLevel":"市","townLevel":"區"},"825":{"city":"高雄","town":"橋頭","lat":22.757591,"lng":120.305809,"cityLevel":"市","townLevel":"區"},"826":{"city":"高雄","town":"梓官","lat":22.7606303,"lng":120.2671523,"cityLevel":"市","townLevel":"區"},"827":{"city":"高雄","town":"彌陀","lat":22.7814893,"lng":120.2507011,"cityLevel":"市","townLevel":"區"},"828":{"city":"高雄","town":"永安","lat":22.818298,"lng":120.224189,"cityLevel":"市","townLevel":"區"},"829":{"city":"高雄","town":"湖內","lat":22.9083136,"lng":120.211713,"cityLevel":"市","townLevel":"區"},"830":{"city":"高雄","town":"鳳山","lat":22.627075,"lng":120.362525,"cityLevel":"市","townLevel":"區"},"831":{"city":"高雄","town":"大寮","lat":22.6055196,"lng":120.3956199,"cityLevel":"市","townLevel":"區"},"832":{"city":"高雄","town":"林園","lat":22.5129453,"lng":120.3946805,"cityLevel":"市","townLevel":"區"},"833":{"city":"高雄","town":"鳥松","lat":22.6598339,"lng":120.364363,"cityLevel":"市","townLevel":"區"},"840":{"city":"高雄","town":"大樹","lat":22.6839054,"lng":120.4143416,"cityLevel":"市","townLevel":"區"},"842":{"city":"高雄","town":"旗山","lat":22.888642,"lng":120.48349,"cityLevel":"市","townLevel":"區"},"843":{"city":"高雄","town":"美濃","lat":22.8947952,"lng":120.5419493,"cityLevel":"市","townLevel":"區"},"844":{"city":"高雄","town":"六龜","lat":22.9984391,"lng":120.6327082,"cityLevel":"市","townLevel":"區"},"845":{"city":"高雄","town":"內門","lat":22.9428391,"lng":120.462606,"cityLevel":"市","townLevel":"區"},"846":{"city":"高雄","town":"杉林","lat":22.9717391,"lng":120.540058,"cityLevel":"市","townLevel":"區"},"847":{"city":"高雄","town":"甲仙","lat":23.0839058,"lng":120.587695,"cityLevel":"市","townLevel":"區"},"848":{"city":"高雄","town":"桃源","lat":23.1592827,"lng":120.7641372,"cityLevel":"市","townLevel":"區"},"849":{"city":"高雄","town":"那瑪夏","lat":23.277092,"lng":120.720243,"cityLevel":"市","townLevel":"區"},"851":{"city":"高雄","town":"茂林","lat":22.886187,"lng":120.663266,"cityLevel":"市","townLevel":"區"},"852":{"city":"高雄","town":"茄萣","lat":22.9065231,"lng":120.1824729,"cityLevel":"市","townLevel":"區"},"880":{"city":"澎湖","town":"馬公","lat":23.566159,"lng":119.578692,"cityLevel":"縣","townLevel":"市"},"881":{"city":"澎湖","town":"西嶼","lat":23.601088,"lng":119.5069847,"cityLevel":"縣","townLevel":"鄉"},"882":{"city":"澎湖","town":"望安","lat":23.3576577,"lng":119.500894,"cityLevel":"縣","townLevel":"鄉"},"883":{"city":"澎湖","town":"七美","lat":23.2067107,"lng":119.4244825,"cityLevel":"縣","townLevel":"鄉"},"884":{"city":"澎湖","town":"白沙","lat":23.666538,"lng":119.598639,"cityLevel":"縣","townLevel":"鄉"},"885":{"city":"澎湖","town":"湖西","lat":23.584072,"lng":119.6528318,"cityLevel":"縣","townLevel":"鄉"},"890":{"city":"金門","town":"金沙","lat":24.488898,"lng":118.413132,"cityLevel":"縣","townLevel":"鎮"},"891":{"city":"金門","town":"金湖","lat":24.4414641,"lng":118.4171018,"cityLevel":"縣","townLevel":"鎮"},"892":{"city":"金門","town":"金寧","lat":24.450966,"lng":118.334887,"cityLevel":"縣","townLevel":"鄉"},"893":{"city":"金門","town":"金城","lat":24.432824,"lng":118.320697,"cityLevel":"縣","townLevel":"鎮"},"894":{"city":"金門","town":"烈嶼","lat":24.4295409,"lng":118.2445892,"cityLevel":"縣","townLevel":"鄉"},"896":{"city":"金門","town":"烏坵","lat":24.9887062,"lng":119.4531826,"cityLevel":"縣","townLevel":"鄉"},"900":{"city":"屏東","town":"屏東","lat":22.662498,"lng":120.4914295,"cityLevel":"縣","townLevel":"市"},"901":{"city":"屏東","town":"三地門","lat":22.7162015,"lng":120.6541301,"cityLevel":"縣","townLevel":"鄉"},"902":{"city":"屏東","town":"霧臺","lat":22.7490518,"lng":120.7282593,"cityLevel":"縣","townLevel":"鄉"},"903":{"city":"屏東","town":"瑪家","lat":22.7086763,"lng":120.6494041,"cityLevel":"縣","townLevel":"鄉"},"904":{"city":"屏東","town":"九如","lat":22.740429,"lng":120.4903298,"cityLevel":"縣","townLevel":"鄉"},"905":{"city":"屏東","town":"里港","lat":22.7792625,"lng":120.4944974,"cityLevel":"縣","townLevel":"鄉"},"906":{"city":"屏東","town":"高樹","lat":22.8267314,"lng":120.600241,"cityLevel":"縣","townLevel":"鄉"},"907":{"city":"屏東","town":"鹽埔","lat":22.7543743,"lng":120.5727019,"cityLevel":"縣","townLevel":"鄉"},"908":{"city":"屏東","town":"長治","lat":22.676538,"lng":120.5272963,"cityLevel":"縣","townLevel":"鄉"},"909":{"city":"屏東","town":"麟洛","lat":22.6506473,"lng":120.5272056,"cityLevel":"縣","townLevel":"鄉"},"911":{"city":"屏東","town":"竹田","lat":22.584724,"lng":120.543981,"cityLevel":"縣","townLevel":"鄉"},"912":{"city":"屏東","town":"內埔","lat":22.6120045,"lng":120.5668293,"cityLevel":"縣","townLevel":"鄉"},"913":{"city":"屏東","town":"萬丹","lat":22.5894894,"lng":120.4850182,"cityLevel":"縣","townLevel":"鄉"},"920":{"city":"屏東","town":"潮州","lat":22.549845,"lng":120.5429633,"cityLevel":"縣","townLevel":"鎮"},"921":{"city":"屏東","town":"泰武","lat":22.5919045,"lng":120.6319498,"cityLevel":"縣","townLevel":"鄉"},"922":{"city":"屏東","town":"來義","lat":22.5261844,"lng":120.6315782,"cityLevel":"縣","townLevel":"鄉"},"923":{"city":"屏東","town":"萬巒","lat":22.5726416,"lng":120.567841,"cityLevel":"縣","townLevel":"鄉"},"924":{"city":"屏東","town":"崁頂","lat":22.5147343,"lng":120.5140493,"cityLevel":"縣","townLevel":"鄉"},"925":{"city":"屏東","town":"新埤","lat":22.4701881,"lng":120.5498736,"cityLevel":"縣","townLevel":"鄉"},"926":{"city":"屏東","town":"南州","lat":22.490404,"lng":120.509879,"cityLevel":"縣","townLevel":"鄉"},"927":{"city":"屏東","town":"林邊","lat":22.431504,"lng":120.5097562,"cityLevel":"縣","townLevel":"鄉"},"928":{"city":"屏東","town":"東港","lat":22.4666854,"lng":120.454361,"cityLevel":"縣","townLevel":"鎮"},"929":{"city":"屏東","town":"琉球","lat":22.348635,"lng":120.3827309,"cityLevel":"縣","townLevel":"鄉"},"931":{"city":"屏東","town":"佳冬","lat":22.419209,"lng":120.5524196,"cityLevel":"縣","townLevel":"鄉"},"932":{"city":"屏東","town":"新園","lat":22.5438351,"lng":120.4614914,"cityLevel":"縣","townLevel":"鄉"},"940":{"city":"屏東","town":"枋寮","lat":22.3655097,"lng":120.5934906,"cityLevel":"縣","townLevel":"鄉"},"941":{"city":"屏東","town":"枋山","lat":22.2639616,"lng":120.6524803,"cityLevel":"縣","townLevel":"鄉"},"942":{"city":"屏東","town":"春日","lat":22.3710005,"lng":120.6290908,"cityLevel":"縣","townLevel":"鄉"},"943":{"city":"屏東","town":"獅子","lat":22.201775,"lng":120.705438,"cityLevel":"縣","townLevel":"鄉"},"944":{"city":"屏東","town":"車城","lat":22.0739409,"lng":120.714276,"cityLevel":"縣","townLevel":"鄉"},"945":{"city":"屏東","town":"牡丹","lat":22.1261502,"lng":120.7743059,"cityLevel":"縣","townLevel":"鄉"},"946":{"city":"屏東","town":"恆春","lat":22.0037401,"lng":120.7472461,"cityLevel":"縣","townLevel":"鎮"},"947":{"city":"屏東","town":"滿州","lat":22.020813,"lng":120.838632,"cityLevel":"縣","townLevel":"鄉"},"950":{"city":"臺東","town":"臺東","lat":22.7548208,"lng":121.1465131,"cityLevel":"縣","townLevel":"市"},"951":{"city":"臺東","town":"綠島","lat":22.6658421,"lng":121.4705314,"cityLevel":"縣","townLevel":"鄉"},"952":{"city":"臺東","town":"蘭嶼","lat":22.0244984,"lng":121.5560627,"cityLevel":"縣","townLevel":"鄉"},"953":{"city":"臺東","town":"延平","lat":22.9025753,"lng":121.0860671,"cityLevel":"縣","townLevel":"鄉"},"954":{"city":"臺東","town":"卑南","lat":22.7827393,"lng":121.0870294,"cityLevel":"縣","townLevel":"鄉"},"955":{"city":"臺東","town":"鹿野","lat":22.9393083,"lng":121.1519859,"cityLevel":"縣","townLevel":"鄉"},"956":{"city":"臺東","town":"關山","lat":23.0474453,"lng":121.1630554,"cityLevel":"縣","townLevel":"鎮"},"957":{"city":"臺東","town":"海端","lat":23.102057,"lng":121.176541,"cityLevel":"縣","townLevel":"鄉"},"958":{"city":"臺東","town":"池上","lat":23.1223101,"lng":121.2151887,"cityLevel":"縣","townLevel":"鄉"},"959":{"city":"臺東","town":"東河","lat":22.9689404,"lng":121.3028937,"cityLevel":"縣","townLevel":"鄉"},"961":{"city":"臺東","town":"成功","lat":23.1050697,"lng":121.3808747,"cityLevel":"縣","townLevel":"鎮"},"962":{"city":"臺東","town":"長濱","lat":23.3149961,"lng":121.4514207,"cityLevel":"縣","townLevel":"鄉"},"963":{"city":"臺東","town":"太麻里","lat":22.615548,"lng":121.007607,"cityLevel":"縣","townLevel":"鄉"},"964":{"city":"臺東","town":"金峰","lat":22.5946397,"lng":120.9607096,"cityLevel":"縣","townLevel":"鄉"},"965":{"city":"臺東","town":"大武","lat":22.340518,"lng":120.890073,"cityLevel":"縣","townLevel":"鄉"},"966":{"city":"臺東","town":"達仁","lat":22.296818,"lng":120.882973,"cityLevel":"縣","townLevel":"鄉"},"970":{"city":"花蓮","town":"花蓮","lat":23.9820651,"lng":121.6067705,"cityLevel":"縣","townLevel":"市"},"971":{"city":"花蓮","town":"新城","lat":24.0392994,"lng":121.6041173,"cityLevel":"縣","townLevel":"鄉"},"972":{"city":"花蓮","town":"秀林","lat":24.1185835,"lng":121.6248326,"cityLevel":"縣","townLevel":"鄉"},"973":{"city":"花蓮","town":"吉安","lat":23.9729455,"lng":121.5636438,"cityLevel":"縣","townLevel":"鄉"},"974":{"city":"花蓮","town":"壽豐","lat":23.8703424,"lng":121.5088259,"cityLevel":"縣","townLevel":"鄉"},"975":{"city":"花蓮","town":"鳳林","lat":23.7447637,"lng":121.4515822,"cityLevel":"縣","townLevel":"鎮"},"976":{"city":"花蓮","town":"光復","lat":23.669342,"lng":121.4233065,"cityLevel":"縣","townLevel":"鄉"},"977":{"city":"花蓮","town":"豐濱","lat":23.6012024,"lng":121.5211488,"cityLevel":"縣","townLevel":"鄉"},"978":{"city":"花蓮","town":"瑞穗","lat":23.4964553,"lng":121.3757788,"cityLevel":"縣","townLevel":"鄉"},"979":{"city":"花蓮","town":"萬榮","lat":23.714875,"lng":121.4109617,"cityLevel":"縣","townLevel":"鄉"},"981":{"city":"花蓮","town":"玉里","lat":23.335527,"lng":121.315197,"cityLevel":"縣","townLevel":"鎮"},"982":{"city":"花蓮","town":"卓溪","lat":23.346478,"lng":121.303451,"cityLevel":"縣","townLevel":"鄉"},"983":{"city":"花蓮","town":"富里","lat":23.1794845,"lng":121.250233,"cityLevel":"縣","townLevel":"鄉"}} \ No newline at end of file diff --git a/assets/notify_test.json b/assets/notify_test.json index 30f82ba6f..87169754e 100644 --- a/assets/notify_test.json +++ b/assets/notify_test.json @@ -1 +1 @@ -{"eew_alert-important-v2":{"title":"🚨 《緊急地震速報 (氣象署發布) 》","body":"花蓮縣壽豐鄉發生地震 強烈搖晃警戒\n〈預估強烈搖晃地區〉\n花蓮 南投 臺東 宜蘭"},"eew_alert-general-v2":{"title":"🚨 《緊急地震速報 (氣象署發布) 》","body":"花蓮縣壽豐鄉發生地震 強烈搖晃警戒\n〈預估強烈搖晃地區〉\n花蓮 南投 臺東 宜蘭"},"eew_alert-silent-v2":{"title":"🚨 《緊急地震速報 (氣象署發布) 》","body":"花蓮縣壽豐鄉發生地震 強烈搖晃警戒\n〈預估強烈搖晃地區〉\n花蓮 南投 臺東 宜蘭"},"eew-important-v2":{"title":"⚠️ 地震速報","body":"10:15左右,花蓮縣壽豐鄉發生地震。震源深度10公里,地震規模M6.1,最大預估震度4。"},"eew-general-v2":{"title":"⚠️ 地震速報","body":"10:15左右,花蓮縣壽豐鄉發生地震。震源深度10公里,地震規模M6.1,最大預估震度4。"},"eew-silence-v2":{"title":"⚠️ 地震速報","body":"10:15左右,花蓮縣壽豐鄉發生地震。震源深度10公里,地震規模M6.1,最大預估震度4。"},"int_report-general-v2":{"title":"📨 震度速報 [07:36]","body":"[震度 5弱] 花蓮縣"},"int_report-silence-v2":{"title":"📨 震度速報 [07:36]","body":"[震度 5弱] 花蓮縣"},"eq-v2":{"title":"📡 強震監視器","body":"臺南市歸仁區 偵測到晃動"},"report-general-v2":{"title":"🔔 地震報告 [小區域有感地震]","body":"00:36左右,花蓮縣近海發生地震。震源深度23.8公里,地震規模M4.0,花蓮縣觀測到最大震度2。"},"report-silence-v2":{"title":"🔔 地震報告 [小區域有感地震]","body":"00:36左右,花蓮縣近海發生地震。震源深度23.8公里,地震規模M4.0,花蓮縣觀測到最大震度2。"},"thunderstorm-general-v2":{"title":"⛈️ 雷雨即時訊息","body":"您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至08/26 17:30"},"weather_major-important-v2":{"title":"📊 臺南市歸仁區 天氣特報","body":"[發布]超大豪雨特報"},"weather_minor-general-v2":{"title":"📊 臺南市歸仁區 天氣特報","body":"[發布]大雨特報\n對流雲系發展旺盛,易有短延時強降雨,新北市已有豪雨發生,今(7日)晚至明(8日)晨基隆北海岸、彰化、雲林、南投、東半部地區及大臺北山區有局部大雨發生的機率,請注意雷擊及強陣風,山區慎防坍方、落石及溪水暴漲。"},"evacuation_major-important-v2":{"title":"🚨 土石流及大規模崩塌警戒","body":"花蓮縣秀林鄉景美村三棧國小(花縣DF174),1小時累積雨量已達2mm、3小時累積雨量已達4.5mm、24小時累積雨量已達304mm,請提高警覺。"},"evacuation_minor-general-v2":{"title":"⚠️ 土石流及大規模崩塌警戒","body":"高雄市桃源區勤和里(玉穗溪)1小時累積雨量已達18.5mm、3小時累積雨量已達18.5mm、24小時累積雨量已達18.5mm,請提高警覺。"},"tsunami-important-v2":{"title":"🌊 海嘯警報發布","body":"海嘯警報已發布\n請儘速前往安全區域避難"},"tsunami-general-v2":{"title":"🌊 海嘯警報發布","body":"海嘯警報已發布\n請儘速前往安全區域避難"},"tsunami-silent-v2":{"title":"🌊 太平洋海嘯消息","body":"頃獲太平洋海嘯警報中心通報,2024年08月18日03時10分(臺灣時間),俄羅斯 堪察加半島東部外海發生規模7﹒4地震,震央位於東經160﹒10度、北緯52﹒70度。該中心研判可能在太平洋地區引發海嘯威脅,氣象署將嚴密監視海嘯的後續影響,隨時提供最新資訊。"},"announcement-general-v2":{"title":"📢 公告","body":"這是一則測試公告。"}} \ No newline at end of file +{"eew_alert-important-v2":{"title":"🚨 《緊急地震速報 (氣象署發布) 》","body":"花蓮縣壽豐鄉發生地震 強烈搖晃警戒\n〈預估強烈搖晃地區〉\n花蓮 南投 臺東 宜蘭"},"eew_alert-general-v2":{"title":"🚨 《緊急地震速報 (氣象署發布) 》","body":"花蓮縣壽豐鄉發生地震 強烈搖晃警戒\n〈預估強烈搖晃地區〉\n花蓮 南投 臺東 宜蘭"},"eew_alert-silent-v2":{"title":"🚨 《緊急地震速報 (氣象署發布) 》","body":"花蓮縣壽豐鄉發生地震 強烈搖晃警戒\n〈預估強烈搖晃地區〉\n花蓮 南投 臺東 宜蘭"},"eew-important-v2":{"title":"⚠️ 地震速報","body":"10:15左右,花蓮縣壽豐鄉發生地震。震源深度10公里,地震規模M6.1,最大預估震度4。"},"eew-general-v2":{"title":"⚠️ 地震速報","body":"10:15左右,花蓮縣壽豐鄉發生地震。震源深度10公里,地震規模M6.1,最大預估震度4。"},"eew-silence-v2":{"title":"⚠️ 地震速報","body":"10:15左右,花蓮縣壽豐鄉發生地震。震源深度10公里,地震規模M6.1,最大預估震度4。"},"int_report-general-v2":{"title":"📨 震度速報 [07:36]","body":"[震度 5弱] 花蓮縣"},"int_report-silence-v2":{"title":"📨 震度速報 [07:36]","body":"[震度 5弱] 花蓮縣"},"eq-v2":{"title":"📡 強震監視器","body":"臺南市歸仁區 偵測到晃動"},"report-general-v2":{"title":"🔔 地震報告 [小區域有感地震]","body":"00:36左右,花蓮縣近海發生地震。震源深度23.8公里,地震規模M4.0,花蓮縣觀測到最大震度2。"},"report-silence-v2":{"title":"🔔 地震報告 [小區域有感地震]","body":"00:36左右,花蓮縣近海發生地震。震源深度23.8公里,地震規模M4.0,花蓮縣觀測到最大震度2。"},"thunderstorm-important-v2":{"title":"⛈️ 山區暴雨","body":"您所在區域附近有暴雨發生的機率,留意溪水暴漲並儘速遠離溪流,持續至8/4 16:34"},"thunderstorm-general-v2":{"title":"⛈️ 雷雨即時訊息","body":"您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至08/26 17:30"},"weather_major-important-v2":{"title":"📊 臺南市歸仁區 天氣特報","body":"[發布]超大豪雨特報"},"weather_minor-general-v2":{"title":"📊 臺南市歸仁區 天氣特報","body":"[發布]大雨特報\n對流雲系發展旺盛,易有短延時強降雨,新北市已有豪雨發生,今(7日)晚至明(8日)晨基隆北海岸、彰化、雲林、南投、東半部地區及大臺北山區有局部大雨發生的機率,請注意雷擊及強陣風,山區慎防坍方、落石及溪水暴漲。"},"evacuation_major-important-v2":{"title":"🌧️ 防災資訊(短時極端降雨紀錄)","body":"臺南市永康區(CAN040 國一N323K) 1 小時累積雨量達到 91.5 mm/hr,請注意自身安全。"},"evacuation_minor-general-v2":{"title":"⚠️ 防災資訊(河川水位-注意)","body":"北寮橋 (水位 73.5m) 已達二級警戒,提高警覺,並密切注意水情變化。"},"tsunami-important-v2":{"title":"🌊 海嘯警報發布","body":"海嘯警報已發布\n請儘速前往安全區域避難"},"tsunami-general-v2":{"title":"🌊 海嘯警報發布","body":"海嘯警報已發布\n請儘速前往安全區域避難"},"tsunami-silent-v2":{"title":"🌊 太平洋海嘯消息","body":"頃獲太平洋海嘯警報中心通報,2024年08月18日03時10分(臺灣時間),俄羅斯 堪察加半島東部外海發生規模7﹒4地震,震央位於東經160﹒10度、北緯52﹒70度。該中心研判可能在太平洋地區引發海嘯威脅,氣象署將嚴密監視海嘯的後續影響,隨時提供最新資訊。"},"announcement-general-v2":{"title":"📢 公告","body":"這是一則測試公告。"}} \ No newline at end of file diff --git a/assets/sprites.json b/assets/sprites.json deleted file mode 100644 index 8236e73b8..000000000 --- a/assets/sprites.json +++ /dev/null @@ -1 +0,0 @@ -{"intensity-7-dark":{"x":288,"y":72,"width":64,"height":64,"pixelRatio":1},"intensity-6-dark":{"x":288,"y":136,"width":64,"height":64,"pixelRatio":1},"lightning-1-10":{"x":288,"y":200,"width":64,"height":64,"pixelRatio":1},"gps":{"x":288,"y":0,"width":72,"height":72,"pixelRatio":1},"lightning-1-5":{"x":0,"y":288,"width":64,"height":64,"pixelRatio":1},"wind-high":{"x":64,"y":288,"width":64,"height":64,"pixelRatio":1},"intensity-5":{"x":128,"y":288,"width":64,"height":64,"pixelRatio":1},"intensity-4":{"x":192,"y":288,"width":64,"height":64,"pixelRatio":1},"intensity-6":{"x":256,"y":288,"width":64,"height":64,"pixelRatio":1},"lightning-0-30":{"x":360,"y":0,"width":64,"height":64,"pixelRatio":1},"intensity-7":{"x":360,"y":64,"width":64,"height":64,"pixelRatio":1},"intensity-1-dark":{"x":360,"y":128,"width":64,"height":64,"pixelRatio":1},"cross-8":{"x":0,"y":0,"width":96,"height":96,"pixelRatio":1},"intensity-3":{"x":360,"y":192,"width":64,"height":64,"pixelRatio":1},"intensity-2":{"x":360,"y":256,"width":64,"height":64,"pixelRatio":1},"cross-9":{"x":96,"y":0,"width":96,"height":96,"pixelRatio":1},"lightning-1-60":{"x":0,"y":352,"width":64,"height":64,"pixelRatio":1},"lightning-0-5":{"x":64,"y":352,"width":64,"height":64,"pixelRatio":1},"wind-low":{"x":128,"y":352,"width":64,"height":64,"pixelRatio":1},"intensity-1":{"x":192,"y":352,"width":64,"height":64,"pixelRatio":1},"cross-7":{"x":0,"y":96,"width":96,"height":96,"pixelRatio":1},"cross-6":{"x":96,"y":96,"width":96,"height":96,"pixelRatio":1},"wind-5":{"x":256,"y":352,"width":64,"height":64,"pixelRatio":1},"cross-4":{"x":192,"y":0,"width":96,"height":96,"pixelRatio":1},"lightning-0-10":{"x":320,"y":352,"width":64,"height":64,"pixelRatio":1},"cross-5":{"x":192,"y":96,"width":96,"height":96,"pixelRatio":1},"wind-middle":{"x":424,"y":0,"width":64,"height":64,"pixelRatio":1},"wind-4":{"x":424,"y":64,"width":64,"height":64,"pixelRatio":1},"cross-1":{"x":0,"y":192,"width":96,"height":96,"pixelRatio":1},"wind-1":{"x":424,"y":128,"width":64,"height":64,"pixelRatio":1},"intensity-4-dark":{"x":424,"y":192,"width":64,"height":64,"pixelRatio":1},"intensity-5-dark":{"x":424,"y":256,"width":64,"height":64,"pixelRatio":1},"wind-3":{"x":424,"y":320,"width":64,"height":64,"pixelRatio":1},"cross-2":{"x":96,"y":192,"width":96,"height":96,"pixelRatio":1},"intensity-9":{"x":0,"y":416,"width":64,"height":64,"pixelRatio":1},"intensity-8":{"x":64,"y":416,"width":64,"height":64,"pixelRatio":1},"cross-3":{"x":192,"y":192,"width":96,"height":96,"pixelRatio":1},"wind-2":{"x":128,"y":416,"width":64,"height":64,"pixelRatio":1},"intensity-9-dark":{"x":192,"y":416,"width":64,"height":64,"pixelRatio":1},"intensity-8-dark":{"x":256,"y":416,"width":64,"height":64,"pixelRatio":1},"lightning-1-30":{"x":320,"y":416,"width":64,"height":64,"pixelRatio":1},"intensity-3-dark":{"x":384,"y":416,"width":64,"height":64,"pixelRatio":1},"intensity-2-dark":{"x":488,"y":0,"width":64,"height":64,"pixelRatio":1},"lightning-0-60":{"x":488,"y":64,"width":64,"height":64,"pixelRatio":1}} \ No newline at end of file diff --git a/assets/sprites.png b/assets/sprites.png deleted file mode 100644 index cf82708f0..000000000 Binary files a/assets/sprites.png and /dev/null differ diff --git a/assets/translations/en.po b/assets/translations/en.po index 75213b79a..b4ec4ef30 100644 --- a/assets/translations/en.po +++ b/assets/translations/en.po @@ -4,18 +4,22 @@ msgstr "" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: en\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" -"X-Crowdin-File-ID: 20\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 26\n" "Project-Id-Version: dpip\n" "Content-Type: text/plain; charset=UTF-8\n" "Language-Team: English\n" "Language: en_US\n" -"PO-Revision-Date: 2025-07-23 03:45\n" +"PO-Revision-Date: 2025-09-01 04:13\n" -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "Current Location" +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "Add a new location" + #: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "Theme" @@ -28,29 +32,29 @@ msgstr "Language" msgid "單位" msgstr "Unit" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "Map" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "Notifications" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "Earthquake Early Warning" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" -msgstr "Monitor" +msgstr "Earthquake Monitor" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "Reports" #: ./lib/app/settings/notify/page.dart:192 msgid "震度速報" -msgstr "Intensity Report" +msgstr "Earthquake Intensity Report" #: ./lib/app/home/_widgets/thunderstorm_card.dart:59 msgid "雷雨即時訊息" @@ -61,12 +65,12 @@ msgid "天氣警特報" msgstr "Weather Advisory" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" -msgstr "Evacuation" +msgid "防災資訊" +msgstr "Emergency information" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" -msgstr "Tsunami" +msgstr "Tsunami information" #: ./lib/route/announcement/announcement.dart:82 msgid "公告" @@ -80,11 +84,11 @@ msgstr "Support Us" msgid "設定" msgstr "Settings" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "Receive All" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "Off" @@ -92,23 +96,23 @@ msgstr "Off" msgid "接收類別" msgstr "Category" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" msgstr "Intensity 1 or higher at current location" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" -msgstr "Tsunami information and tsunami warning" +msgstr "Tsunami information, Tsunami warning" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "Tsunami warning only" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "Receive for current location" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" msgstr "Intensity 4 or higher at current location" @@ -120,7 +124,7 @@ msgstr "Sound Test" msgid "發送公告時" msgstr "When sending an announcement" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" msgstr "The sound test is a local notification performed on the device, used only to confirm whether sound can be played properly when receiving alerts. This test does not send any requests to any server" @@ -132,7 +136,7 @@ msgstr "Please set your current location to enable notifications" msgid "地震速報" msgstr "Earthquake Warning" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "Earthquake" @@ -140,7 +144,7 @@ msgstr "Earthquake" msgid "天氣" msgstr "Weather" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "Tsunami" @@ -148,23 +152,21 @@ msgstr "Tsunami" msgid "其他" msgstr "Other" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "Severe" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "海嘯警報發布時\n" -"沿海地區鄉鎮" -msgstr "When a tsunami warning is issued for coastal towns and townships" +msgid "海嘯警報發布時" +msgstr "When a tsunami warning is issued" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "General" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "海嘯警報發布時\n" -"上述除外地區" -msgstr "When a tsunami warning is issued for non-coastal areas" +msgid "海嘯消息發布時" +msgstr "When a tsunami message is issued" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息(無聲通知)" @@ -176,7 +178,7 @@ msgstr "When the Pacific information is issued" #: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 msgid "強震監視器(一般)" -msgstr "Monitor(General)" +msgstr "Earthquake Monitor (General)" #: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 msgid "偵測到晃動" @@ -188,7 +190,7 @@ msgstr "Intensity Report" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 msgid "所在地(鄉鎮)實測震度 3 以上" -msgstr "Local (City/Town/District) measured intensity is greater than 3." +msgstr "Local (City/Town/District) measured intensity is greater than 3" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:35 msgid "震度速報(無聲通知)" @@ -196,15 +198,15 @@ msgstr "Intensity Report (Silent)" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36 msgid "所在地(鄉鎮)實測震度 1 以上" -msgstr "Local (City/Town/District) measured intensity is greater than 1." +msgstr "Local (City/Town/District) measured intensity is greater than 1" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:33 msgid "地震報告(一般)" -msgstr "Earthquake Report" +msgstr "Earthquake Report (General)" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:33 msgid "所在地(縣市)實測震度 3 以上" -msgstr "Local (Municipality/County) measured intensity is greater than 3." +msgstr "Local (Municipality/County) measured intensity is greater than 3" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:34 msgid "地震報告(無聲通知)" @@ -212,7 +214,7 @@ msgstr "Earthquake Report (Silent)" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:34 msgid "所在地(縣市)實測震度 1 以上" -msgstr "Local (Municipality/County) measured intensity is greater than 1." +msgstr "Local (Municipality/County) measured intensity is greater than 1" #: ./lib/app/settings/notify/_lib/utils.dart:13 msgid "已更新通知設定" @@ -220,25 +222,25 @@ msgstr "Updated notification setting" #: ./lib/app/settings/notify/_lib/utils.dart:17 msgid "更新通知設定失敗" -msgstr "Notification settings updated successfully" +msgstr "Failed To Update Notification Settings" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:34 msgid "緊急地震速報(重大)" -msgstr "Failed to update notification settings" +msgstr "Earthquake Early Warning (Critical)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:35 msgid "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 4 以上" -msgstr "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 4." +msgstr "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 4" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:39 msgid "緊急地震速報(一般)" -msgstr "Emergency Earthquake Early Warning" +msgstr "Emergency Earthquake Early Warning (General)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:40 msgid "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 2 以上" -msgstr "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 2." +msgstr "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 2" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:44 msgid "緊急地震速報(無聲)" @@ -247,7 +249,7 @@ msgstr "Emergency Earthquake Early Warning (Silent)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:45 msgid "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 1 以上" -msgstr "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 1." +msgstr "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 1" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:48 msgid "地震速報(重大)" @@ -255,15 +257,15 @@ msgstr "Earthquake Early Warning (Critical)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:48 msgid "所在地(鄉鎮)預估震度 4 以上" -msgstr "Local (City/Town/District) estimated intensity is greater than 4." +msgstr "Local (City/Town/District) estimated intensity is greater than 4" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:49 msgid "地震速報(一般)" -msgstr "Earthquake Early Warning" +msgstr "Earthquake Early Warning (General)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:49 msgid "所在地(鄉鎮)預估震度 2 以上" -msgstr "Local (City/Town/District) estimated intensity is greater than 2." +msgstr "Local (City/Town/District) estimated intensity is greater than 2" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:50 msgid "地震速報(無聲)" @@ -271,30 +273,35 @@ msgstr "Earthquake Early Warning (Silent)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:50 msgid "所在地(鄉鎮)預估震度 1 以上" -msgstr "Local (City/Town/District) estimated intensity is greater than 1." +msgstr "Local (City/Town/District) estimated intensity is greater than 1" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" -msgstr "When the local area(township) issues an evacuating warning" +msgid "所在地(鄉鎮)發布防災警訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" -msgstr "When the local area(township) issues an evacuating warning" +msgid "所在地(鄉鎮)發布防災資訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 msgid "所在地(鄉鎮)發布紅色燈號之\n" "天氣警特報" -msgstr "" +msgstr "The location (township) issues a red signal\n" +"Weather Warning" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:40 msgid "所在地(鄉鎮)發布上述除外燈號之\n" "天氣警特報" -msgstr "" +msgstr "The location (township) where the above-mentioned exceptions are issued\n" +"Weather Warning" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" -msgstr "" +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "The location (township) issues rainstorm alert in the mountains" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" +msgstr "The location (township) issues instant thunderstorm information" #: ./lib/app/settings/unit/page.dart:28 msgid "使用華氏度" @@ -314,7 +321,7 @@ msgstr "System Language" #: ./lib/app/settings/locale/page.dart:40 msgid "協助翻譯" -msgstr "Help us translate!" +msgstr "Help us translate" #: ./lib/app/settings/locale/page.dart:41 msgid "點擊這裡來幫助我們改進 DPIP 的翻譯" @@ -332,60 +339,61 @@ msgstr "Translated {translated} ・ Approved {approved}" msgid "來源語言" msgstr "Source Language" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "Unable to connect to the store, please try again later" -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "Unable to find the item, please try again later" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "Reload" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "Loading store items" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" -msgstr "" +msgstr "As an app dedicated to providing real-time earthquake information, DPIP currently has no advertising or other profit models. In order to maintain high-quality services, we need to bear the costs of server operation, seismic data acquisition and transmission, and subsequent function development and maintenance.\n\n" +"Every donation you make below will go directly toward these operating costs, helping DPIP to continue to provide you with services in a sustainable manner. Thank you for your understanding and generosity!" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "Subscription" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "{price}/month" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "One-time" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" msgstr "Unable to connect to the {store}, please try again later." -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" -msgstr "" +msgstr "Restoring your purchased subscription" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" msgstr "Restore purchases" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" msgstr "Terms of use" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" msgstr "Privacy policy" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "Location" @@ -415,7 +423,7 @@ msgstr "Adjust settings of map in DPIP" #: ./lib/app/settings/page.dart:87 msgid "推播通知設定與通知音效測試" -msgstr "" +msgstr "Push notification settings and notification sound test" #: ./lib/app/settings/page.dart:94 msgid "資訊" @@ -423,7 +431,7 @@ msgstr "Information" #: ./lib/app/settings/page.dart:99 msgid "掌握 ExpTech Studio 的最新公告與資訊" -msgstr "" +msgstr "Get the latest announcements and news from ExpTech Studio" #: ./lib/app/changelog/page.dart:54 msgid "更新日誌" @@ -431,11 +439,11 @@ msgstr "Release Notes" #: ./lib/app/settings/page.dart:106 msgid "瀏覽 DPIP 的歷次更新紀錄" -msgstr "" +msgstr "View DPIP's Previous Update Records" #: ./lib/app/settings/page.dart:113 msgid "幫助我們維護伺服器的穩定和長久發展" -msgstr "" +msgstr "Help us maintain the stability and long-term development of the server" #: ./lib/app/settings/page.dart:119 msgid "第三方套件授權" @@ -469,51 +477,163 @@ msgstr "App Logs" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "All information should be considered authoritative only if it is consistent with CWA." -#: ./lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "Unable to obtain Notification Permission" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "Unable to obtain Location Permission" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "Unable to obtain Self-Start Permission" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "Power saving" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "Unable to obtain permission" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "To use the Auto-Location feature, please allow Notification Permission for DPIP in settings, then try again." + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "Cancel" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "Update Automatically" -#: ./lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "Update your current location periodically" -#: ./lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "The automatic location update feature will use the GPS on your device to update your location based on your geographical position periodically, providing real-time weather and earthquake information, so you can stay up-to-date with the latest local conditions." -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" -msgstr "Special Municipality/County" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" -msgstr "Not Set" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" -msgstr "City/Town/District" +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" +msgstr "" -#: ./lib/app/settings/location/select/page.dart:26 +#: ./lib/app/settings/location/select/page.dart:38 msgid "縣市" msgstr "Special Municipalities/County" -#: ./lib/app/settings/location/select/page.dart:38 +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "Current Location" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "Monitor" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "Radar" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "Temperature" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "Precipitation" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "Wind/Gust" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "Simple" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "Base Map" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "Initial Layer" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" msgstr "Animation frame rate" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "Affects the smoothness of the seismic wave simulation in the Earthquake Monitor." + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" msgstr "Excessively high the animation frame rate may cause lag or device overheating" @@ -545,10 +665,6 @@ msgstr "System Color" msgid "使用系統顏色" msgstr "Use System Color" -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "Cancel" - #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "Confirm" @@ -561,9 +677,9 @@ msgstr "Severe thunderstorms or heavy rain are occurring near your area. Please msgid "服務區域外,僅在臺灣各地可用" msgstr "Out of service area. Available only in Taiwan" -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" -msgstr "Radar" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" +msgstr "Not Set" #: ./lib/app/home/_widgets/weather_header.dart:127 msgid "體感約 {apparent}°" @@ -573,31 +689,39 @@ msgstr "Apparent {apparent}°" msgid "尚未設定所在地" msgstr "Location not set" -#: ./lib/app/map/_lib/managers/monitor.dart:874 +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1089 msgid "第 {serial} 報" -msgstr "{serial} report" +msgstr "of {serial}" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。" -msgstr "At around {time}, a felt earthquake near {location} had an estimated magnitude of M{magnitude} and a max intensity of {intensity}" +msgstr "Around {time}, felt earthquake near {location} estimated M{magnitude} and max intensity {intensity}." -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" -msgstr "Estimated intensity at current location" +msgstr "Estimated" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" -msgstr "The earthquake" +msgstr "Waves" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" -msgstr " seconds" +msgstr " Seconds" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" -msgstr "arrived" +msgstr "Arrived" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" msgstr "Updated to {version}" @@ -613,7 +737,7 @@ msgstr "Unable to load update logs, please try again later." msgid "重試" msgstr "Retry" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "Next" @@ -623,15 +747,15 @@ msgstr "Disaster Prevention Information Platform" #: ./lib/app/welcome/2-exptech/page.dart:83 msgid "我們是誰?" -msgstr "" +msgstr "Who are we?" #: ./lib/app/welcome/2-exptech/page.dart:88 msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" -msgstr "" +msgstr "ExpTech Studio is a group of mostly students, with an average age of under 20 and a headcount of 15+. Members are students from northern, central and southern Taiwan, Japan, South Korea and China." #: ./lib/app/welcome/2-exptech/page.dart:93 msgid "我們的初衷" -msgstr "" +msgstr "Our original intention" #: ./lib/app/welcome/2-exptech/page.dart:98 msgid "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" @@ -639,299 +763,307 @@ msgstr "" #: ./lib/app/welcome/3-notice/page.dart:38 msgid "注意事項" -msgstr "" +msgstr "Precautions" #: ./lib/app/welcome/3-notice/page.dart:75 msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" -msgstr "" +msgstr "Depending on the network status, server status, application status, upstream data source status, etc., there is a possibility that information will not be received. We will try our best to avoid such situations, but we cannot guarantee that they will not happen." #: ./lib/app/welcome/3-notice/page.dart:88 msgid "強烈搖晃有機率比通知早抵達使用者所在地。" -msgstr "" +msgstr "Strong shaking has a chance of reaching the user's location before the notification." #: ./lib/app/welcome/3-notice/page.dart:99 msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" -msgstr "" +msgstr "Earthquake early warning is the result of rapid calculation and may have large errors. It should be understood and used with caution." #: ./lib/app/welcome/3-notice/page.dart:110 msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" -msgstr "" +msgstr "Any action that is not officially approved could lead to legal consequences. It's essential to follow all applicable rules and regulations." #: ./lib/app/welcome/1-about/page.dart:40 msgid "歡迎使用 DPIP" -msgstr "" +msgstr "Welcome to DPIP" #: ./lib/app/welcome/1-about/page.dart:81 msgid "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" -msgstr "" +msgstr "DPIP is an app designed by a local Taiwanese team that integrates information from TREM-Net (Taiwan Real-time Earthquake Observation Network) and data from the Central Weather Administration to provide an integrated, single and convenient disaster prevention information application." -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" -msgstr "" +msgstr "Delivering real-time disaster prevention information via notifications when major disasters occur" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" -msgstr "" +msgstr "Use location to automatically update location settings and provide local real-time disaster prevention information" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" -msgstr "" +msgstr "Allow DPIP to run continuously in the background for real-time disaster notification information." #: ./lib/route/image_viewer/image_viewer.dart:228 msgid "儲存" msgstr "Save" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" -msgstr "" +msgstr "Used to store data visualization images provided by the Central Meteorological Administration or ExpTech" -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" -msgstr "" +msgstr "Permission request" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" -msgstr "" +msgstr "Users are required to manually go to settings to enable relevant permissions." -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "Permissions" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" -msgstr "" +msgstr "We always stand with our users and work hard for their privacy." -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "Map Layers" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "Select the layer you want to display" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" -msgstr "Simple" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" +msgstr "Reports" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "Weather" -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "Temperature" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" +msgstr "Units: {unit}" -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "Precipitation" - -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "Wind/Gust" - -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" -msgstr "" +msgstr "Long press to set the start point of playback" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" -msgstr "" +msgstr "Current time" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" -msgstr "" +msgstr "Play start" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "Today" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" -msgstr "10min" +msgstr "10 min" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" -msgstr "1hr" +msgstr "1 hr" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" -msgstr "3hr" +msgstr "3 hr" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" -msgstr "6hr" +msgstr "6 hr" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" -msgstr "12hr" +msgstr "12 hr" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" -msgstr "24hr" +msgstr "24 hr" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" -msgstr "2d" +msgstr "2 d" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" -msgstr "3d" +msgstr "3 d" + +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "No data" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" +msgstr "There are currently no active earthquake early warnings" + +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" msgstr "Estimated M{magnitude}, max intensity {intensity}" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" -msgstr "" +msgstr "in {countdown}s" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" -msgstr "" +msgstr "Arrived" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" -msgstr "Recent Reports" +msgstr "Recent Earthquake Reports" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "More" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" -msgstr "No. {number}" +msgstr "No. {number} Significantly Felt Earthquake" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "Local Earthquake" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "Magnitude" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "Depth" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "Web" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" msgstr "Event Time" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "Location" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "Observed Intensities" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" -msgstr "Intensity Map Image" +msgstr "Earthquake Intensity Map Image" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "Intensity Map Image" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "Max PGA Image" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "Max PGV Image" #: ./lib/route/announcement/announcement.dart:12 msgid "錯誤" -msgstr "" +msgstr "Mistake" #: ./lib/route/announcement/announcement.dart:13 msgid "已解決" -msgstr "" +msgstr "Resolved" #: ./lib/route/announcement/announcement.dart:14 msgid "影響:小" -msgstr "" +msgstr "Impact: Small" #: ./lib/route/announcement/announcement.dart:15 msgid "影響:中" -msgstr "" +msgstr "Impact: Medium" #: ./lib/route/announcement/announcement.dart:16 msgid "影響:大" -msgstr "" +msgstr "Impact: Large" #: ./lib/route/announcement/announcement.dart:18 msgid "維修" -msgstr "" +msgstr "Impact: Major" #: ./lib/route/announcement/announcement.dart:19 msgid "測試" -msgstr "" +msgstr "Test" #: ./lib/route/announcement/announcement.dart:20 msgid "變更" -msgstr "" +msgstr "Change" #: ./lib/route/announcement/announcement.dart:21 msgid "完成" -msgstr "" +msgstr "Done" #: ./lib/route/announcement/announcement.dart:22 msgid "地震相關" -msgstr "" +msgstr "Seismic" #: ./lib/route/announcement/announcement.dart:23 msgid "氣象相關" -msgstr "" +msgstr "Weather related" #: ./lib/route/announcement/announcement.dart:29 msgid "未知" -msgstr "" +msgstr "Unknown" #: ./lib/route/announcement/announcement.dart:103 msgid "目前沒有公告" -msgstr "" +msgstr "There is no announcement." #: ./lib/route/announcement/announcement.dart:223 msgid "公告詳情" -msgstr "" - -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "" +msgstr "Announcement Details" #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" -msgstr "" +msgstr "Please go to the app settings and allow the \"Photos and Media\" permissions and try again." #: ./lib/route/image_viewer/image_viewer.dart:70 msgid "再試一次" -msgstr "" +msgstr "Try again" #: ./lib/route/image_viewer/image_viewer.dart:110 msgid "已儲存圖片" -msgstr "" +msgstr "Saved pictures" #: ./lib/route/image_viewer/image_viewer.dart:126 msgid "儲存圖片時發生錯誤" -msgstr "" +msgstr "An error occurred while saving the image" #: ./lib/utils/extensions/int.dart:13 msgid "0級" @@ -971,7 +1103,7 @@ msgstr "6+" #: ./lib/utils/extensions/int.dart:22 msgid "7級" -msgstr "7" +msgstr "Intensity 7" #: ./lib/utils/weather_icon.dart:283 msgid "晴" @@ -1039,7 +1171,7 @@ msgstr "" #: ./lib/utils/weather_icon.dart:299 msgid "晴有雷雹" -msgstr "" +msgstr "Clear with thunder and hail" #: ./lib/utils/weather_icon.dart:300 msgid "晴大雷雨" @@ -1047,19 +1179,19 @@ msgstr "" #: ./lib/utils/weather_icon.dart:301 msgid "晴大雷雹" -msgstr "" +msgstr "Clear sky with heavy thunder and hail" #: ./lib/utils/weather_icon.dart:303 msgid "多雲" -msgstr "" +msgstr "Partly cloudy" #: ./lib/utils/weather_icon.dart:304 msgid "多雲有霾" -msgstr "" +msgstr "Cloudy with haze" #: ./lib/utils/weather_icon.dart:305 msgid "多雲有靄" -msgstr "" +msgstr "Cloudy with haze" #: ./lib/utils/weather_icon.dart:306 msgid "多雲有閃電" @@ -1067,7 +1199,7 @@ msgstr "" #: ./lib/utils/weather_icon.dart:322 msgid "多雲伴有雷" -msgstr "" +msgstr "Cloudy with thunder" #: ./lib/utils/weather_icon.dart:308 msgid "多雲有霧" @@ -1079,11 +1211,11 @@ msgstr "" #: ./lib/utils/weather_icon.dart:310 msgid "多雲有雨雪" -msgstr "" +msgstr "Cloudy with rain and snow" #: ./lib/utils/weather_icon.dart:311 msgid "多雲有大雪" -msgstr "" +msgstr "Cloudy with heavy snow" #: ./lib/utils/weather_icon.dart:312 msgid "多雲有雪珠" @@ -1119,7 +1251,7 @@ msgstr "" #: ./lib/utils/weather_icon.dart:320 msgid "多雲大雷雨" -msgstr "" +msgstr "Cloudy with Thunderstorm" #: ./lib/utils/weather_icon.dart:321 msgid "多雲大雷雹" @@ -1127,77 +1259,93 @@ msgstr "" #: ./lib/utils/weather_icon.dart:323 msgid "陰" -msgstr "" +msgstr "Overcast" #: ./lib/utils/weather_icon.dart:324 msgid "陰有霾" -msgstr "" +msgstr "Overcast with Haze" #: ./lib/utils/weather_icon.dart:325 msgid "陰有靄" -msgstr "" +msgstr "Overcast with Mist" #: ./lib/utils/weather_icon.dart:326 msgid "陰有閃電" -msgstr "" +msgstr "Overcast with Lighting" #: ./lib/utils/weather_icon.dart:342 msgid "陰天伴有雷" -msgstr "" +msgstr "Cloudy with Thunder" #: ./lib/utils/weather_icon.dart:328 msgid "陰有霧" -msgstr "" +msgstr "Overcast with Fog" #: ./lib/utils/weather_icon.dart:329 msgid "陰有雨" -msgstr "" +msgstr "Overcast with Rain" #: ./lib/utils/weather_icon.dart:330 msgid "陰有雨雪" -msgstr "" +msgstr "Overcast with Rain/Snow" #: ./lib/utils/weather_icon.dart:331 msgid "陰有大雪" -msgstr "" +msgstr "Overcast with Heavy Snow" #: ./lib/utils/weather_icon.dart:332 msgid "陰有雪珠" -msgstr "" +msgstr "Overcast with Snow" #: ./lib/utils/weather_icon.dart:333 msgid "陰有冰珠" -msgstr "" +msgstr "Cloudy with ice beads" #: ./lib/utils/weather_icon.dart:334 msgid "陰有陣雪" -msgstr "" +msgstr "Cloudy with snow showers" #: ./lib/utils/weather_icon.dart:335 msgid "陰陣雨雪" -msgstr "" +msgstr "Cloudy with rain and snow" #: ./lib/utils/weather_icon.dart:336 msgid "陰有雹" -msgstr "" +msgstr "Cloudy with Hail" #: ./lib/utils/weather_icon.dart:337 msgid "陰有雷雨" -msgstr "" +msgstr "Cloudy with thunderstorm" #: ./lib/utils/weather_icon.dart:338 msgid "陰有雷雪" -msgstr "" +msgstr "Cloudy with thunder and snow" #: ./lib/utils/weather_icon.dart:339 msgid "陰有雷雹" -msgstr "" +msgstr "Cloudy with thunder and hail" #: ./lib/utils/weather_icon.dart:340 msgid "陰大雷雨" -msgstr "" +msgstr "Cloudy with heavy thunderstorm" #: ./lib/utils/weather_icon.dart:341 msgid "陰大雷雹" +msgstr "Heavy thunder and hail" + +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "{town} {townLevel}, {city} {cityLevel}" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" msgstr "" +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "{city} {cityLevel}" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "{town} {townLevel}" + diff --git a/assets/translations/ja.po b/assets/translations/ja.po index 20df84740..17dfebdad 100644 --- a/assets/translations/ja.po +++ b/assets/translations/ja.po @@ -4,18 +4,22 @@ msgstr "" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: ja\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" -"X-Crowdin-File-ID: 20\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 26\n" "Project-Id-Version: dpip\n" "Content-Type: text/plain; charset=UTF-8\n" "Language-Team: Japanese\n" "Language: ja_JP\n" -"PO-Revision-Date: 2025-07-23 03:45\n" +"PO-Revision-Date: 2025-09-01 03:15\n" -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "現在地" +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "新しい場所を追加" + #: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "テーマ" @@ -28,23 +32,23 @@ msgstr "言語" msgid "單位" msgstr "単位" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "地図" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "通知" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "緊急地震速報" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" msgstr "強震モニター" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "地震情報" @@ -61,10 +65,10 @@ msgid "天氣警特報" msgstr "天気警報" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" -msgstr "避難情報" +msgid "防災資訊" +msgstr "防災インフォメーション" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" msgstr "津波情報" @@ -80,11 +84,11 @@ msgstr "応援する" msgid "設定" msgstr "設定" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "すべて受信" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "オフ" @@ -92,25 +96,25 @@ msgstr "オフ" msgid "接收類別" msgstr "受信カテゴリ" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" -msgstr "現在地震度1以上で受信" +msgstr "現在地震度 1 以上で受信" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" msgstr "津波警報・情報" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "津波警報のみ受信" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "現地のみ受信" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" -msgstr "現在地震度4以上で受信" +msgstr "現在地震度 4 以上で受信" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:31 msgid "音效測試" @@ -120,7 +124,7 @@ msgstr "サウンドテスト" msgid "發送公告時" msgstr "通知受信時" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" msgstr "サウンドテストはこのデバイス上でのみ実行されるテストです、通知受信時にデバイスが効果音を正常に再生できるかどうかを確認するためにのみ使用されます" @@ -132,7 +136,7 @@ msgstr "通知機能を使用する為に現在地を設定してください" msgid "地震速報" msgstr "地震速報" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "地震" @@ -140,7 +144,7 @@ msgstr "地震" msgid "天氣" msgstr "天気" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "津波" @@ -148,25 +152,21 @@ msgstr "津波" msgid "其他" msgstr "その他" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "重大" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "海嘯警報發布時\n" -"沿海地區鄉鎮" -msgstr "津波警報が発令された時\n" -"沿岸地域" +msgid "海嘯警報發布時" +msgstr "津波警報発令中" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "一般" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "海嘯警報發布時\n" -"上述除外地區" -msgstr "津波警報が発令された時\n" -"沿岸地域を除いた地域" +msgid "海嘯消息發布時" +msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息(無聲通知)" @@ -279,12 +279,12 @@ msgid "所在地(鄉鎮)預估震度 1 以上" msgstr "現在地(郷/鎮)測りにより震度 1 超え" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" -msgstr "現在地(郷/鎮)に避難注意報が発令された時" +msgid "所在地(鄉鎮)發布防災警訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" -msgstr "現在地(郷/鎮)に避難情報が発信された時" +msgid "所在地(鄉鎮)發布防災資訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 msgid "所在地(鄉鎮)發布紅色燈號之\n" @@ -297,9 +297,12 @@ msgid "所在地(鄉鎮)發布上述除外燈號之\n" msgstr "現在地(郷/鎮)にその以外の天気注意報/特報が発令され" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" -msgstr "現在地(郷/鎮)に雷雨/山地にわか雨リアルタイム情報が発信された時" +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" +msgstr "" #: ./lib/app/settings/unit/page.dart:28 msgid "使用華氏度" @@ -337,61 +340,61 @@ msgstr "{translated} 翻訳済み・{approved} 校正済み" msgid "來源語言" msgstr "ソース言語" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "ストアーへの接続異常" -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "該当商品が見つかりません" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "再読み込み" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "ストアーの商品読み込み中" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" msgstr "DPIP はリアルタイムで地震情報の提供に努めているアプリケーションとして、今までに広告や他の収益方法などはございません。サービスの品質をより高く保たれるため、サーバーの運行、地震データの取り込みや伝送、またはより豊富な機能の開発やメンテナンスなどのコストを負担しております。\n\n" "貴台がお選びになるサポートプランは全て以上の運営コストの一部のお支払いに活用しておりまして、DPIP をより穏やかなサービスができることを支えております。ご理解、ご厚意に感謝しています!" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "サブスクリプション" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "{price}/毎月" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "一回払い" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" msgstr "{store}に接続できませんでした。しばらく時間をおいてから、もう一度お試しください。" -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" msgstr "ご購入内容を復元しています" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" msgstr "購入を復元" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" msgstr "利用規約" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" msgstr "プライバシーポリシー" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "位置" @@ -430,7 +433,7 @@ msgstr "情報" #: ./lib/app/settings/page.dart:99 msgid "掌握 ExpTech Studio 的最新公告與資訊" -msgstr "ExpTech Studio の最新のお知らせと情報をチェック" +msgstr "ExpTech Studioの最新のお知らせと情報をチェック" #: ./lib/app/changelog/page.dart:54 msgid "更新日誌" @@ -476,51 +479,163 @@ msgstr "アプリログ" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "すべての情報は、中央気象署(CWA)の公式発表を基準にしてください。" -#: ./lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "電力を守る策略" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "権限を取得できませんでした" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "キャンセル" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "自動起動" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "常に許可" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "自動更新" -#: ./lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "定期的に現在地を更新する" -#: ./lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "この機能には、デバイスのGPSを利用して、地理的な位置情報に基づいて所在地を更新します。リアルタイムの天気情報や地震情報を提供し、最新の地域状況を取得します。" -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" -msgstr "直轄市/県市" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" -msgstr "未設定" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" -msgstr "区町村" +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/settings/location/select/page.dart:26 +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" +msgstr "" + +#: ./lib/app/settings/location/select/page.dart:38 msgid "縣市" msgstr "県/市" -#: ./lib/app/settings/location/select/page.dart:38 +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "現在地" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "強震モニター" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "レーダー" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "気温" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "降水量" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "風向・風速" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "シンプル" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "Google" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "ベースマップ" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "初期レイヤー" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" msgstr "動画のフレームレート" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "強震モニターの地震波アニメーションの滑らかさを調整します" + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" msgstr "速すぎたフレームレートはラッグや設備発熱に至る可能性があります" @@ -552,10 +667,6 @@ msgstr "システム色" msgid "使用系統顏色" msgstr "システムの色を使う" -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "キャンセル" - #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "確認" @@ -568,9 +679,9 @@ msgstr "お住まいの地域付近で激しい雷雨または降雨が発生し msgid "服務區域外,僅在臺灣各地可用" msgstr "台湾以外ではご利用いただけません" -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" -msgstr "レーダー" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" +msgstr "未設定" #: ./lib/app/home/_widgets/weather_header.dart:127 msgid "體感約 {apparent}°" @@ -580,33 +691,41 @@ msgstr "体感温度 {apparent}°" msgid "尚未設定所在地" msgstr "現在地が設定されていません" -#: ./lib/app/map/_lib/managers/monitor.dart:874 +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1089 msgid "第 {serial} 報" -msgstr "第 {serial} 報" +msgstr "第{serial}報" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。" msgstr "{time}ごろ、{location}付近で地震。推定M{magnitude}、最大震度{intensity}。" -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。" +msgstr "{time}ごろ、{location}付近で地震。推定M{magnitude}、深さ{depth}キロメートル。" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" msgstr "現在地の予想" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" msgstr "地震波" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" msgstr " 秒" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" msgstr "到達" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" -msgstr "{version} に更新されました" +msgstr "{version}に更新されました" #: ./lib/utils/weather_icon.dart:282 msgid "取得天氣異常" @@ -620,7 +739,7 @@ msgstr "変更履歴を読み込めませんでした。" msgid "重試" msgstr "再試行" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "次" @@ -672,19 +791,15 @@ msgstr "DPIPへようこそ" msgid "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "DPIP は台湾本土のグループが作ったアプリケーションで、TREM-Net(台湾即時地震観測ネット)と台湾中央気象局のデータを整合して、より整合、単一で便利な防災情報アプリケーションを提供しております。" -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "非常災害が発生した時、通知で即時防災情報を伝えます" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" msgstr "定位により自動的に現在地を更新し、当地である即時防災情報を受けられます" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "電力を守る策略" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "バックグラウンドでも DPIP の運行ができることを同意し、より即時な通知や情報を受けられることになります。" @@ -692,175 +807,191 @@ msgstr "バックグラウンドでも DPIP の運行ができることを同意 msgid "儲存" msgstr "保存" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "台湾中央気象署またはExpTechから提供されたデータ可視化画像をセーブすることに用いることになります" -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "権限を要求" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "ユーザー手動で設定まで相関な権限を開けることが必要です。" -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "権限" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "私たちはユーザーの側に立ち、休むことなくユーザーのプライバシーに努めております。" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "地図レイヤー" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "表示する地図のレイヤーを選択してください" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" -msgstr "線" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" +msgstr "地震情報" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "気象" -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "気温" - -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "降水量" - -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "風向・風速" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" +msgstr "単位:{unit}" -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" -msgstr "長タッチし、プレイ起点を設定する" +msgstr "長タッチして再生の起点を設定する" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" -msgstr "今の時間" +msgstr "表示中の時刻" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" -msgstr "プレイ起点" +msgstr "再生の起点" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" -msgstr "プレイ進度" +msgstr "再生中" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "今日" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" msgstr "10分間" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" msgstr "1時間" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" msgstr "3時間" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" msgstr "6時間" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" msgstr "12時間" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" msgstr "24時間" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" msgstr "2日間" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" msgstr "3日間" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" msgstr "緊急地震速報は発表されていません" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" +msgstr "M{magnitude}、深さ{depth}キロメートル" + +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" msgstr "M{magnitude}、最大震度{intensity}" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" msgstr "到達まであと{countdown}秒" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" msgstr "到達し" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" msgstr "最近の地震情報" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "さらに表示" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" msgstr "ID #{number} の顕著な地震" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "局地的地震" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "マグニチュード" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "震源の深さ" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "Webで見る" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" -msgstr "発生時刻" +msgstr "発震時刻" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "震源地" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "各地の震度" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "地震情報図" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "震度分布図" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "地動最大加速度" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "地動最大速度" @@ -910,7 +1041,7 @@ msgstr "気象相関" #: ./lib/route/announcement/announcement.dart:29 msgid "未知" -msgstr "未知" +msgstr "不明" #: ./lib/route/announcement/announcement.dart:103 msgid "目前沒有公告" @@ -920,10 +1051,6 @@ msgstr "現在お知らせはありません" msgid "公告詳情" msgstr "お知らせの詳細" -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "権限を取得できませんでした" - #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" msgstr "アプリケーション設定に「画像や映像」の権限をお開けてから、もう一度試すことをお願いします。" @@ -1208,3 +1335,19 @@ msgstr "曇りのち雨、大雷あり" msgid "陰大雷雹" msgstr "曇りのち大雹、大雷あり" +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "{city}{cityLevel} {town}{townLevel}" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "{city} {town}" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "{city}{cityLevel}" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "{town}{townLevel}" + diff --git a/assets/translations/ko.po b/assets/translations/ko.po index 302d46bb3..11d13b4b3 100644 --- a/assets/translations/ko.po +++ b/assets/translations/ko.po @@ -4,69 +4,73 @@ msgstr "" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: ko\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" -"X-Crowdin-File-ID: 20\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 26\n" "Project-Id-Version: dpip\n" "Content-Type: text/plain; charset=UTF-8\n" "Language-Team: Korean\n" "Language: ko_KR\n" -"PO-Revision-Date: 2025-07-23 03:45\n" +"PO-Revision-Date: 2025-09-01 03:15\n" -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" +msgstr "현재 지역" + +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" msgstr "" #: ./lib/app/settings/page.dart:52 msgid "主題" -msgstr "" +msgstr "주제" #: ./lib/app/settings/page.dart:60 msgid "語言" -msgstr "" +msgstr "언어" #: ./lib/app/settings/page.dart:68 msgid "單位" -msgstr "" +msgstr "단위" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" -msgstr "" +msgstr "지도" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" -msgstr "" +msgstr "알림" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "긴급 지진 속보" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" -msgstr "" +msgstr "강진 모니터" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" -msgstr "" +msgstr "지진 보고" #: ./lib/app/settings/notify/page.dart:192 msgid "震度速報" -msgstr "" +msgstr "진도 속보" #: ./lib/app/home/_widgets/thunderstorm_card.dart:59 msgid "雷雨即時訊息" -msgstr "" +msgstr "실시간 뇌우 정보" #: ./lib/app/settings/notify/page.dart:223 msgid "天氣警特報" -msgstr "" +msgstr "기상특보" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" -msgstr "" +msgid "防災資訊" +msgstr "방재 정보" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" -msgstr "쓰나미 정보" +msgstr "해일 정보" #: ./lib/route/announcement/announcement.dart:82 msgid "公告" @@ -74,105 +78,103 @@ msgstr "공지" #: ./lib/app/settings/page.dart:112 msgid "贊助我們" -msgstr "" +msgstr "저희를 후원해주세요" #: ./lib/route/image_viewer/image_viewer.dart:70 msgid "設定" -msgstr "" +msgstr "설정" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" -msgstr "" +msgstr "모두 수신" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" -msgstr "" +msgstr "닫기" #: ./lib/app/settings/notify/_widgets/eew_notify_section.dart:37 msgid "接收類別" -msgstr "" +msgstr "수신 카테고리" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" -msgstr "" +msgstr "현재 위치 진도 1 이상" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" -msgstr "" +msgstr "해일 정보, 해일 경보" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" -msgstr "" +msgstr "해일 경보만 수신" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" -msgstr "" +msgstr "현재 위치 수신" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" -msgstr "" +msgstr "현재 위치 진도 4 이상" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:31 msgid "音效測試" -msgstr "" +msgstr "사운드 테스트" #: ./lib/app/settings/notify/(5.basic)/announcement/page.dart:32 msgid "發送公告時" -msgstr "" +msgstr "공지 발송 시" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" -msgstr "" +msgstr "사운드 테스트는 기기에서 수행되는 로컬 알림입니다. 기기가 알림을 수신했을 때 음향 효과를 정상적으로 재생할 수 있는지 확인하는 데만 사용됩니다. 이 테스트는 요청을 서버에 전송하지 않습니다" #: ./lib/app/settings/notify/page.dart:135 msgid "請先設定所在地來使用通知功能" -msgstr "" +msgstr "알림 기능을 사용하시려면 먼저 위치를 설정해 주세요" #: ./lib/app/settings/notify/page.dart:142 msgid "地震速報" -msgstr "" +msgstr "지진 속보" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" -msgstr "" +msgstr "지진" #: ./lib/app/settings/notify/page.dart:204 msgid "天氣" -msgstr "" +msgstr "날씨" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" -msgstr "" +msgstr "해일" #: ./lib/app/settings/notify/page.dart:266 msgid "其他" -msgstr "" +msgstr "기타" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" -msgstr "" +msgstr "중대" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "海嘯警報發布時\n" -"沿海地區鄉鎮" -msgstr "" +msgid "海嘯警報發布時" +msgstr "해일 경보 발령 시" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "일반" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "海嘯警報發布時\n" -"上述除外地區" -msgstr "" +msgid "海嘯消息發布時" +msgstr "해일 소식 발표 시" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息(無聲通知)" -msgstr "" +msgstr "태평양 해일 정보(무음 알림)" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息發布時" -msgstr "" +msgstr "태평양 해일 정보 발령 시" #: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 msgid "強震監視器(一般)" @@ -180,129 +182,132 @@ msgstr "강진 모니터(일반)" #: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 msgid "偵測到晃動" -msgstr "흔들림이 감지되었습니다" +msgstr "흔들림 감지" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 msgid "震度速報(一般)" -msgstr "" +msgstr "진도 속보(일반)" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 msgid "所在地(鄉鎮)實測震度 3 以上" -msgstr "소재지(향ㆍ진) 실측 진도 3 이상" +msgstr "현재 위치(향, 진) 실측 진도 3 이상" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:35 msgid "震度速報(無聲通知)" -msgstr "" +msgstr "진도 속보(무음 알림)" #: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36 msgid "所在地(鄉鎮)實測震度 1 以上" -msgstr "소재지(향ㆍ진) 실측 진도 1 이상" +msgstr "현재 위치(향, 진) 실측 진도 1 이상" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:33 msgid "地震報告(一般)" -msgstr "" +msgstr "지진 보고(일반)" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:33 msgid "所在地(縣市)實測震度 3 以上" -msgstr "소재지(현ㆍ시) 실측 진도 3 이상" +msgstr "현재 위치(현, 시) 실측 진도 3 이상" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:34 msgid "地震報告(無聲通知)" -msgstr "" +msgstr "지진 보고(무음 알림)" #: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:34 msgid "所在地(縣市)實測震度 1 以上" -msgstr "소재지(현ㆍ시) 실측 진도 1 이상" +msgstr "현재 위치(현, 시) 실측 진도 1 이상" #: ./lib/app/settings/notify/_lib/utils.dart:13 msgid "已更新通知設定" -msgstr "" +msgstr "알림 설정 갱신" #: ./lib/app/settings/notify/_lib/utils.dart:17 msgid "更新通知設定失敗" -msgstr "" +msgstr "알림 설정 갱신 실패" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:34 msgid "緊急地震速報(重大)" -msgstr "" +msgstr "긴급 지진 속보(중대)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:35 msgid "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 4 以上" -msgstr "" +msgstr "​최대 진도 5 약 이상, 현재 위치(향, 진) 예상 진도 4 이상" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:39 msgid "緊急地震速報(一般)" -msgstr "" +msgstr "긴급 지진 속보(일반)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:40 msgid "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 2 以上" -msgstr "" +msgstr "최대 진도 5 약 이상, 현재 위치(향, 진) 예상 진도 2 이상" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:44 msgid "緊急地震速報(無聲)" -msgstr "" +msgstr "긴급 지진 속보(무음)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:45 msgid "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 1 以上" -msgstr "" +msgstr "최대 진도 5 약 이상, 현재 위치(향, 진) 예상 진도 1 이상" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:48 msgid "地震速報(重大)" -msgstr "" +msgstr "지진 속보(중대)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:48 msgid "所在地(鄉鎮)預估震度 4 以上" -msgstr "소재지(향ㆍ진) 예상 진도 4 이상" +msgstr "현재 위치(향, 진) 예상 진도 4 이상" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:49 msgid "地震速報(一般)" -msgstr "" +msgstr "지진 속보(일반)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:49 msgid "所在地(鄉鎮)預估震度 2 以上" -msgstr "소재지(향ㆍ진) 예상 진도 2 이상" +msgstr "현재 위치(향, 진) 예상 진도 2 이상" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:50 msgid "地震速報(無聲)" -msgstr "" +msgstr "지진 속보(무음)" #: ./lib/app/settings/notify/(1.eew)/eew/page.dart:50 msgid "所在地(鄉鎮)預估震度 1 以上" -msgstr "소재지(향ㆍ진) 예상 진도 1 이상" +msgstr "현재 위치(향, 진) 예상 진도 1 이상" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" -msgstr "소재지(향ㆍ진)에 피난 경보가 발령된 경우" +msgid "所在地(鄉鎮)發布防災警訊時" +msgstr "소재지(향진)에서 재난경보 발령 시" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" -msgstr "소재지(향ㆍ진)에 피난 정보가 발령된 경우" +msgid "所在地(鄉鎮)發布防災資訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 msgid "所在地(鄉鎮)發布紅色燈號之\n" "天氣警特報" -msgstr "소재지(향ㆍ진)에서 적색 기상 경보 특보를 발령" +msgstr "현재 위치(향, 진)에 적색 기상 경보 특보를 발령" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:40 msgid "所在地(鄉鎮)發布上述除外燈號之\n" "天氣警特報" -msgstr "소재지(향ㆍ진)에서 기상 경보를 발령" +msgstr "현재 위치(향, 진)에 기상 경보를 발령" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" -msgstr "소재지(향ㆍ진)으로 뇌우 실시간 정보 또는 산간지역 호우 시 전송합니다." +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" +msgstr "소재지(향ㆍ진)으로 뇌우 실시간 정보" #: ./lib/app/settings/unit/page.dart:28 msgid "使用華氏度" -msgstr "" +msgstr "화씨 사용" #: ./lib/app/settings/unit/page.dart:29 msgid "切換溫度顯示單位為華氏度 (℉)" -msgstr "" +msgstr "온도 표시를 화씨(°F)로 전환" #: ./lib/app/settings/locale/page.dart:31 msgid "顯示語言" @@ -310,7 +315,7 @@ msgstr "표시 언어" #: ./lib/app/settings/locale/page.dart:32 msgid "系統語言" -msgstr "" +msgstr "시스템 언어" #: ./lib/app/settings/locale/page.dart:40 msgid "協助翻譯" @@ -322,7 +327,7 @@ msgstr "여기를 눌러 DPIP 번역 개선을 도와주세요" #: ./lib/app/settings/locale/select/page.dart:46 msgid "選擇語言" -msgstr "" +msgstr "언어 선택" #: ./lib/app/settings/locale/select/page.dart:67 msgid "已翻譯 {translated}・已校對 {approved}" @@ -332,70 +337,71 @@ msgstr "번역됨 {translated}・승인됨 {approved}" msgid "來源語言" msgstr "출처 언어" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" -msgstr "" +msgstr "스토어에 연결할 수 없습니다, 잠시 후 다시 시도해 주세요" -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" -msgstr "" +msgstr "상품을 찾을 수 없습니다, 잠시 후 다시 시도해 주세요" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" -msgstr "" +msgstr "새로 고침" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" -msgstr "" +msgstr "스토어 상품 로드 중" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" -msgstr "" +msgstr "DPIP는 실시간 지진 정보를 제공하는 데 전념하는 앱으로서, 현재 광고나 다른 수익 모델이 없습니다. 고품질 서비스를 유지하기 위해 우리는 서버 운영, 지진 데이터 확보 및 전송, 그리고 후속 기능 개발 및 유지 보수에 드는 비용을 부담해야 합니다.\n" +"​아래에서 선택해 주시는 모든 후원금은 이러한 운영 비용을 지불하는 데 직접 사용되어, DPIP가 여러분께 지속적으로 안정적인 서비스를 제공하는 데 도움이 될 것입니다. 여러분의 이해와 너그러운 마음에 감사드립니다!" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" -msgstr "" +msgstr "정기 구독" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" -msgstr "" +msgstr "{price}/월" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" -msgstr "" +msgstr "일회성 후원" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" -msgstr "" +msgstr "{store}에 연결할 수 없습니다, 잠시 후 다시 시도해 주세요." -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" -msgstr "" +msgstr "구매했던 구독 복원" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" -msgstr "" +msgstr "구매 기록 복원" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" -msgstr "" +msgstr "이용 약관" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" -msgstr "" +msgstr "개인 정보 보호 정책" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" -msgstr "" +msgstr "위치" #: ./lib/app/settings/page.dart:39 msgid "設定你的所在地來接收當地的即時資訊" -msgstr "" +msgstr "현재 위치를 설정하여 해당 지역 실시간 정보 수신" #: ./lib/app/settings/page.dart:48 msgid "介面" -msgstr "" +msgstr "인터페이스" #: ./lib/app/settings/page.dart:53 msgid "調整 DPIP 整體的外觀與顏色" @@ -403,27 +409,27 @@ msgstr "DPIP 전체의 외관과 색상을 조정합니다" #: ./lib/app/settings/page.dart:61 msgid "調整 DPIP 的顯示語言" -msgstr "DPIP의 표시 언어 조정" +msgstr "DPIP 표시 언어 조정" #: ./lib/app/settings/page.dart:69 msgid "調整 DPIP 顯示數值時使用的單位" -msgstr "" +msgstr "DPIP의 표시 단위 조정" #: ./lib/app/settings/page.dart:75 msgid "調整 DPIP 地圖的設定" -msgstr "" +msgstr "DPIP 지도 설정 조정" #: ./lib/app/settings/page.dart:87 msgid "推播通知設定與通知音效測試" -msgstr "" +msgstr "푸시 알림 설정 및 알림음 테스트" #: ./lib/app/settings/page.dart:94 msgid "資訊" -msgstr "" +msgstr "정보" #: ./lib/app/settings/page.dart:99 msgid "掌握 ExpTech Studio 的最新公告與資訊" -msgstr "" +msgstr "ExpTech Studio의 최신 공지 및 정보 확인" #: ./lib/app/changelog/page.dart:54 msgid "更新日誌" @@ -431,7 +437,7 @@ msgstr "업데이트 로그" #: ./lib/app/settings/page.dart:106 msgid "瀏覽 DPIP 的歷次更新紀錄" -msgstr "" +msgstr "DPIP 이전 업데이트 기록" #: ./lib/app/settings/page.dart:113 msgid "幫助我們維護伺服器的穩定和長久發展" @@ -439,27 +445,27 @@ msgstr "서버의 안정과 장기적인 발전 돕기" #: ./lib/app/settings/page.dart:119 msgid "第三方套件授權" -msgstr "서드파티 라이브러리 라이선스" +msgstr "제3자 라이브러리 라이선스" #: ./lib/app/settings/page.dart:120 msgid "DPIP 的實現歸功於開放源始碼" -msgstr "" +msgstr "DPIP의 구현은 오픈 소스에 힘입었습니다" #: ./lib/app/settings/page.dart:162 msgid "除錯" -msgstr "디버그" +msgstr "오류 수정" #: ./lib/app/settings/page.dart:166 msgid "應用程式版本" -msgstr "" +msgstr "앱 버전" #: ./lib/app/settings/page.dart:172 msgid "裝置資訊" -msgstr "" +msgstr "기기 정보" #: ./lib/app/settings/page.dart:178 msgid "複製通知 Token" -msgstr "" +msgstr "알림 토큰 복사" #: ./lib/app/debug/logs/page.dart:16 msgid "App 日誌" @@ -469,57 +475,169 @@ msgstr "앱 로그" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "모든 정보는 대만 기상청에서 발표한 내용을 기준으로 합니다." -#: ./lib/app/settings/location/page.dart:422 -msgid "自動更新" +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" msgstr "" -#: ./lib/app/settings/location/page.dart:423 -msgid "定期更新目前的所在地" +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" msgstr "" -#: ./lib/app/settings/location/page.dart:433 -msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" msgstr "" -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "전원 절약 설정" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "권한 획득 불가" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" msgstr "" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" msgstr "" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" msgstr "" -#: ./lib/app/settings/location/select/page.dart:26 -msgid "縣市" +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "취소" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "" + +#: ./lib/app/settings/location/page.dart:231 +msgid "自動更新" +msgstr "자동 업데이트" + +#: ./lib/app/settings/location/page.dart:232 +msgid "定期更新目前的所在地" +msgstr "현재 위치 정기적으로 업데이트" + +#: ./lib/app/settings/location/page.dart:242 +msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" +msgstr "자동 위치 기능은 기기의 GPS를 사용하며, DPIP가 꺼져 있거나 사용 중이 아닐 때도 사용자의 위치 정보를 기반으로 현재 위치를 자동으로 업데이트합니다. 이를 통해 실시간 날씨와 지진 정보를 제공하여 사용자가 항상 현지 최신 상황을 파악할 수 있도록 합니다." + +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" msgstr "" #: ./lib/app/settings/location/select/page.dart:38 +msgid "縣市" +msgstr "현/시" + +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" +msgstr "현재 위치" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 -msgid "底圖" +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "레이더" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "기온" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "강우" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "풍향/풍속" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" msgstr "" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "Google" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 +msgid "底圖" +msgstr "배경 레이어" + +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" -msgstr "" +msgstr "기본 지도" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" +msgstr "애니메이션 주사율" + +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" msgstr "" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" -msgstr "" +msgstr "지나치게 높은 애니메이션 주사율은 끊김 현상이나 기기 발열을 일으킬 수 있습니다" #: ./lib/app/settings/theme/page.dart:30 msgid "主題模式" -msgstr "" +msgstr "테마 모드" #: ./lib/app/settings/theme/select/page.dart:57 msgid "淺色" @@ -535,19 +653,15 @@ msgstr "시스템 테마 따르기" #: ./lib/app/settings/theme/select/page.dart:22 msgid "主題色" -msgstr "" +msgstr "테마 색상" #: ./lib/app/settings/theme/page.dart:46 msgid "系統色彩" -msgstr "" +msgstr "시스템 색상" #: ./lib/app/settings/theme/page.dart:88 msgid "使用系統顏色" -msgstr "" - -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "취소" +msgstr "시스템 색상 사용" #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" @@ -555,55 +669,63 @@ msgstr "확인" #: ./lib/app/home/_widgets/thunderstorm_card.dart:76 msgid "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。" -msgstr "" +msgstr "현재 위치 부근 강한 뇌우 또는 비. {time}까지 계속될 수 있으니 주의." #: ./lib/app/home/_widgets/location_out_of_service.dart:24 msgid "服務區域外,僅在臺灣各地可用" -msgstr "" +msgstr "서비스 지역 외에서는 사용할 수 없으며, 대만에서만 이용 가능합니다" -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" -msgstr "레이더" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" +msgstr "설정되지 않음" #: ./lib/app/home/_widgets/weather_header.dart:127 msgid "體感約 {apparent}°" -msgstr "" +msgstr "체감 온도 {apparent}" #: ./lib/app/home/_widgets/location_not_set_card.dart:30 msgid "尚未設定所在地" -msgstr "위치가 설정되지 않았습니다." +msgstr "현재 위치가 설정되지 않았습니다" -#: ./lib/app/map/_lib/managers/monitor.dart:874 -msgid "第 {serial} 報" +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1089 +msgid "第 {serial} 報" +msgstr "제 {serial} 보" + +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。" +msgstr "{time}경, {location} 부근 체감 지진 발생. 예상 규모 M{magnitude}, 현재 위치 최대 진도 {intensity}." + +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" -msgstr "" +msgstr "현재 위치 예상" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" -msgstr "" +msgstr "지진파" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" -msgstr "" +msgstr " 초" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" -msgstr "" +msgstr "도착" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" -msgstr "" +msgstr "{version} 업데이트" #: ./lib/utils/weather_icon.dart:282 msgid "取得天氣異常" -msgstr "" +msgstr "날씨 이상 정보 확인" #: ./lib/app/changelog/page.dart:109 msgid "無法載入更新日誌,請稍後再試。" @@ -613,21 +735,21 @@ msgstr "업데이트 로그를 불러올 수 없습니다. 나중에 다시 시 msgid "重試" msgstr "다시 시도" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "다음 단계" #: ./lib/app/welcome/1-about/page.dart:60 msgid "防災資訊平台" -msgstr "방재정보 플랫폼" +msgstr "방재 정보 플랫폼" #: ./lib/app/welcome/2-exptech/page.dart:83 msgid "我們是誰?" -msgstr "저희에 관하여?" +msgstr "저희에 관하여?" #: ./lib/app/welcome/2-exptech/page.dart:88 msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" -msgstr "ExpTech Studio는 대부분 학생으로 구성된 팀으로, 평균 연령이 20세 이하이며, 15명 이상의 인원이 참여하고 있습니다. 멤버들은 대만 북부, 중부, 남부, 일본, 한국, 중국의 학생들로 구성되어 있습니다." +msgstr "ExpTech Studio는 대부분 학생들로 구성되어 있으며, 평균 연령 20 세 미만, 15 명 이상의 단체입니다. 구성원은 대만 북·중·남부, 일본, 한국, 중국의 학생들로 이루어져 있습니다." #: ./lib/app/welcome/2-exptech/page.dart:93 msgid "我們的初衷" @@ -639,23 +761,23 @@ msgstr "설립 초기의 목적은 컴퓨터와 기술에 관심과 능력이 #: ./lib/app/welcome/3-notice/page.dart:38 msgid "注意事項" -msgstr "주의사항" +msgstr "주의 사항" #: ./lib/app/welcome/3-notice/page.dart:75 msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" -msgstr "네트워크 상태, 서버 상태, 애플리케이션 상태, 상위 데이터 소스 상태 등 여러 요인에 따라 정보를 수신되지 않을 가능성이 있으며, 이를 방지하기 위해 최선을 다하겠지만 발생하지 않을 것이라고 보장하지는 않습니다." +msgstr "네트워크 상태, 서버 상태, 애플리케이션 상태, 상위 데이터 소스 상태 등에 따라 정보를 받지 못할 가능성이 있습니다. 저희는 이러한 상황을 피하기 위해 최선을 다하지만, 반드시 발생하지 않는다고 보장할 수는 없습니다." #: ./lib/app/welcome/3-notice/page.dart:88 msgid "強烈搖晃有機率比通知早抵達使用者所在地。" -msgstr "강한 진동이 알림보다 사용자 위치에 먼저 도착할 가능성이 있습니다." +msgstr "강한 흔들림이 알림보다 먼저 사용자 위치에 도착할 가능성이 있습니다." #: ./lib/app/welcome/3-notice/page.dart:99 msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" -msgstr "지진 속보는 빠른 계산 결과로, 상당한 오차가 있을 수 있으니 이해하고 신중히 사용해 주세요." +msgstr "지진 속보는 신속한 계산 결과이므로, 오차가 클 수 있습니다. 이 점을 이해하고 신중하게 사용해야 합니다." #: ./lib/app/welcome/3-notice/page.dart:110 msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" -msgstr "공식적으로 인정되지 않은 모든 행위는 법적 위험을 부담할 수 있으므로 관련 규범을 준수해야 합니다." +msgstr "공식적으로 인정되지 않는 모든 행위는 법적 위험을 초래할 수 있으니, 관련 규정을 반드시 준수해 주십시오." #: ./lib/app/welcome/1-about/page.dart:40 msgid "歡迎使用 DPIP" @@ -665,19 +787,15 @@ msgstr "DPIP에 오신 것을 환영합니다" msgid "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "DPIP는 TREM-Net(대만의 실시간 지진 관측 네트워크) 정보 및 중앙 기상청 자료를 통합하여 통합, 단일 및 편리한 방재 정보 응용 프로그램을 제공하는 대만 현지 팀이 설계한 앱입니다." -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "중대 재해 발생 시 알림으로 즉각 재난 대비 정보를 전달합니다" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" -msgstr "GPS를 이용하여 소재지 위치를 자동으로 업데이트하고, 현지의 즉각적인 방재 정보를 제공합니다." +msgstr "GPS를 이용하여 소재지 위치를 자동으로 업데이트하고, 현지의 즉각적인 방재 정보를 제공합니다" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "전원 절약 설정" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "실시간 재난 알림 정보를 위해 DPIP가 백그라운드에서 계속 실행되도록 허용합니다." @@ -685,293 +803,305 @@ msgstr "실시간 재난 알림 정보를 위해 DPIP가 백그라운드에서 msgid "儲存" msgstr "이미지 저장" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "대만 기상청 또는 ExpTech에서 제공하는 데이터 시각화 이미지를 저장하는 데 사용" -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "권한 요청" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "사용자가 수동으로 설정에서 관련 권한을 활성화해야 합니다." -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "권한" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "우리는 항상 사용자와 함께하며 사용자의 프라이버시를 위해 끊임없이 노력합니다." -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" -msgstr "" +msgstr "지도 레이어" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" -msgstr "" +msgstr "표시 지도 레이더 선택" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" -msgstr "" - -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "기온" +msgstr "기상" -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "강우" - -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "풍향/풍속" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" +msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" -msgstr "" +msgstr "길게 눌러 재생 시작 지점 설정" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" -msgstr "" +msgstr "현재 시간" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" -msgstr "" +msgstr "재생 시작 지점" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" -msgstr "" +msgstr "재생 진행도" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "오늘" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" -msgstr "10분" +msgstr "10 분" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" -msgstr "1시간" +msgstr "1 시간" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" -msgstr "3시간" +msgstr "3 시간" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" -msgstr "6시간" +msgstr "6 시간" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" -msgstr "12시간" +msgstr "12 시간" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" -msgstr "24시간" +msgstr "24 시간" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" -msgstr "2일" +msgstr "2 일" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" -msgstr "3일" +msgstr "3 일" + +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" +msgstr "현재 유효 지진 속보 없음" + +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" -msgstr "" +msgstr "규모 M{magnitude}, 현재 위치 예상 진도 {intensity}" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" -msgstr "" +msgstr "{countdown}초 후 도착" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" -msgstr "" +msgstr "도착" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" -msgstr "" +msgstr "최근 지진 현황" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" -msgstr "" +msgstr "더 보기" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" -msgstr "" +msgstr "번호 {number} 강한 체감 지진" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" -msgstr "" +msgstr "소구역 체감 지진" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" -msgstr "" +msgstr "지진 규모" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" -msgstr "" +msgstr "진원 깊이" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" -msgstr "" +msgstr "보고 페이지" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" -msgstr "" +msgstr "지진 발생 시간" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" -msgstr "" +msgstr "에 위치" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" -msgstr "각지의 진도" +msgstr "각 지역 진도" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "지진 보고" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "진도" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "최대 지반 가속도" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "최대 지반 속도" #: ./lib/route/announcement/announcement.dart:12 msgid "錯誤" -msgstr "" +msgstr "오류" #: ./lib/route/announcement/announcement.dart:13 msgid "已解決" -msgstr "" +msgstr "해결 완료" #: ./lib/route/announcement/announcement.dart:14 msgid "影響:小" -msgstr "" +msgstr "영향:작음" #: ./lib/route/announcement/announcement.dart:15 msgid "影響:中" -msgstr "" +msgstr "영향:보통" #: ./lib/route/announcement/announcement.dart:16 msgid "影響:大" -msgstr "" +msgstr "영향:큼" #: ./lib/route/announcement/announcement.dart:18 msgid "維修" -msgstr "" +msgstr "유지 보수" #: ./lib/route/announcement/announcement.dart:19 msgid "測試" -msgstr "" +msgstr "테스트" #: ./lib/route/announcement/announcement.dart:20 msgid "變更" -msgstr "" +msgstr "변경" #: ./lib/route/announcement/announcement.dart:21 msgid "完成" -msgstr "" +msgstr "완성" #: ./lib/route/announcement/announcement.dart:22 msgid "地震相關" -msgstr "" +msgstr "지진 관련" #: ./lib/route/announcement/announcement.dart:23 msgid "氣象相關" -msgstr "" +msgstr "기상 관련" #: ./lib/route/announcement/announcement.dart:29 msgid "未知" -msgstr "" +msgstr "알 수 없음" #: ./lib/route/announcement/announcement.dart:103 msgid "目前沒有公告" -msgstr "" +msgstr "현재 공지 없음" #: ./lib/route/announcement/announcement.dart:223 msgid "公告詳情" -msgstr "" - -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "" +msgstr "공지 내용" #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" -msgstr "" +msgstr "응용 프로그램 설정에서 '사진 및 미디어' 권한을 찾아 허용 후에 다시 시도해 주세요." #: ./lib/route/image_viewer/image_viewer.dart:70 msgid "再試一次" -msgstr "" +msgstr "다시 시도해 주세요" #: ./lib/route/image_viewer/image_viewer.dart:110 msgid "已儲存圖片" -msgstr "" +msgstr "이미지 저장 완료" #: ./lib/route/image_viewer/image_viewer.dart:126 msgid "儲存圖片時發生錯誤" -msgstr "" +msgstr "이미지 저장 중 오류" #: ./lib/utils/extensions/int.dart:13 msgid "0級" -msgstr "" +msgstr "0급" #: ./lib/utils/extensions/int.dart:14 msgid "1級" -msgstr "" +msgstr "1급" #: ./lib/utils/extensions/int.dart:15 msgid "2級" -msgstr "" +msgstr "2급" #: ./lib/utils/extensions/int.dart:16 msgid "3級" -msgstr "" +msgstr "3급" #: ./lib/utils/extensions/int.dart:17 msgid "4級" -msgstr "" +msgstr "4급" #: ./lib/utils/extensions/int.dart:18 msgid "5弱" -msgstr "" +msgstr "5약" #: ./lib/utils/extensions/int.dart:19 msgid "5強" -msgstr "" +msgstr "5강" #: ./lib/utils/extensions/int.dart:20 msgid "6弱" -msgstr "" +msgstr "6약" #: ./lib/utils/extensions/int.dart:21 msgid "6強" -msgstr "" +msgstr "6강" #: ./lib/utils/extensions/int.dart:22 msgid "7級" -msgstr "" +msgstr "7급" #: ./lib/utils/weather_icon.dart:283 msgid "晴" @@ -983,7 +1113,7 @@ msgstr "맑음・연무" #: ./lib/utils/weather_icon.dart:285 msgid "晴有靄" -msgstr "맑음・안개" +msgstr "맑음・옅은 안개" #: ./lib/utils/weather_icon.dart:286 msgid "晴有閃電" @@ -995,7 +1125,7 @@ msgstr "맑음・천둥" #: ./lib/utils/weather_icon.dart:288 msgid "晴有霧" -msgstr "맑음・안개" +msgstr "맑음・짙은 안개" #: ./lib/utils/weather_icon.dart:289 msgid "晴有雨" @@ -1003,7 +1133,7 @@ msgstr "맑음・비" #: ./lib/utils/weather_icon.dart:290 msgid "晴有雨雪" -msgstr "맑음・눈비" +msgstr "맑음・비/눈" #: ./lib/utils/weather_icon.dart:291 msgid "晴有大雪" @@ -1011,11 +1141,11 @@ msgstr "맑음・폭설" #: ./lib/utils/weather_icon.dart:292 msgid "晴有雪珠" -msgstr "맑음・눈알" +msgstr "맑음・싸라기 눈" #: ./lib/utils/weather_icon.dart:293 msgid "晴有冰珠" -msgstr "맑음・우박" +msgstr "맑음・진눈깨비" #: ./lib/utils/weather_icon.dart:294 msgid "晴有陣雪" @@ -1023,7 +1153,7 @@ msgstr "맑음・소나기 눈" #: ./lib/utils/weather_icon.dart:295 msgid "晴陣雨雪" -msgstr "맑음・소나기 눈비" +msgstr "맑음・소나기 비/눈" #: ./lib/utils/weather_icon.dart:296 msgid "晴有雹" @@ -1035,95 +1165,95 @@ msgstr "맑음・뇌우" #: ./lib/utils/weather_icon.dart:298 msgid "晴有雷雪" -msgstr "" +msgstr "맑음・천둥 눈" #: ./lib/utils/weather_icon.dart:299 msgid "晴有雷雹" -msgstr "" +msgstr "맑음・천둥 우박" #: ./lib/utils/weather_icon.dart:300 msgid "晴大雷雨" -msgstr "" +msgstr "맑음・강한 뇌우" #: ./lib/utils/weather_icon.dart:301 msgid "晴大雷雹" -msgstr "" +msgstr "맑음・강한 천둥 우박" #: ./lib/utils/weather_icon.dart:303 msgid "多雲" -msgstr "" +msgstr "구름 많음" #: ./lib/utils/weather_icon.dart:304 msgid "多雲有霾" -msgstr "" +msgstr "구름 많음・연무" #: ./lib/utils/weather_icon.dart:305 msgid "多雲有靄" -msgstr "" +msgstr "구름 많음・옅은 안개" #: ./lib/utils/weather_icon.dart:306 msgid "多雲有閃電" -msgstr "" +msgstr "구름 많음・번개" #: ./lib/utils/weather_icon.dart:322 msgid "多雲伴有雷" -msgstr "" +msgstr "구름 많음・천둥" #: ./lib/utils/weather_icon.dart:308 msgid "多雲有霧" -msgstr "" +msgstr "구름 많음・짙은 안개" #: ./lib/utils/weather_icon.dart:309 msgid "多雲有雨" -msgstr "" +msgstr "구름 많음・비" #: ./lib/utils/weather_icon.dart:310 msgid "多雲有雨雪" -msgstr "" +msgstr "구름 많음・비/눈" #: ./lib/utils/weather_icon.dart:311 msgid "多雲有大雪" -msgstr "" +msgstr "구름 많음・폭설" #: ./lib/utils/weather_icon.dart:312 msgid "多雲有雪珠" -msgstr "" +msgstr "구름 많음・싸라기눈" #: ./lib/utils/weather_icon.dart:313 msgid "多雲有冰珠" -msgstr "" +msgstr "구름 많음・진눈깨비" #: ./lib/utils/weather_icon.dart:314 msgid "多雲有陣雪" -msgstr "" +msgstr "구름 많음・소나기 눈" #: ./lib/utils/weather_icon.dart:315 msgid "多雲陣雨雪" -msgstr "" +msgstr "구름 많음・소나기 눈/비" #: ./lib/utils/weather_icon.dart:316 msgid "多雲有雹" -msgstr "" +msgstr "구름 많음・우박" #: ./lib/utils/weather_icon.dart:317 msgid "多雲有雷雨" -msgstr "" +msgstr "구름 많음・뇌우" #: ./lib/utils/weather_icon.dart:318 msgid "多雲有雷雪" -msgstr "" +msgstr "구름 많음・천둥/눈" #: ./lib/utils/weather_icon.dart:319 msgid "多雲有雷雹" -msgstr "" +msgstr "구름 많음・천둥/우박" #: ./lib/utils/weather_icon.dart:320 msgid "多雲大雷雨" -msgstr "" +msgstr "구름 많음・강한 뇌우" #: ./lib/utils/weather_icon.dart:321 msgid "多雲大雷雹" -msgstr "" +msgstr "구름 많음・강한 천둥/우박" #: ./lib/utils/weather_icon.dart:323 msgid "陰" @@ -1131,51 +1261,51 @@ msgstr "흐림" #: ./lib/utils/weather_icon.dart:324 msgid "陰有霾" -msgstr "맑음・연무" +msgstr "흐림・연무" #: ./lib/utils/weather_icon.dart:325 msgid "陰有靄" -msgstr "맑음・안개" +msgstr "흐림・안개" #: ./lib/utils/weather_icon.dart:326 msgid "陰有閃電" -msgstr "" +msgstr "흐림・번개" #: ./lib/utils/weather_icon.dart:342 msgid "陰天伴有雷" -msgstr "맑음・천둥" +msgstr "흐림・천둥" #: ./lib/utils/weather_icon.dart:328 msgid "陰有霧" -msgstr "맑음・안개" +msgstr "흐림・옅은 안개" #: ./lib/utils/weather_icon.dart:329 msgid "陰有雨" -msgstr "맑음・비" +msgstr "흐림・비" #: ./lib/utils/weather_icon.dart:330 msgid "陰有雨雪" -msgstr "" +msgstr "흐림・눈/비" #: ./lib/utils/weather_icon.dart:331 msgid "陰有大雪" -msgstr "" +msgstr "흐림・폭설" #: ./lib/utils/weather_icon.dart:332 msgid "陰有雪珠" -msgstr "" +msgstr "흐림・싸라기눈" #: ./lib/utils/weather_icon.dart:333 msgid "陰有冰珠" -msgstr "" +msgstr "흐림・진눈깨비" #: ./lib/utils/weather_icon.dart:334 msgid "陰有陣雪" -msgstr "" +msgstr "흐림・소나기 눈" #: ./lib/utils/weather_icon.dart:335 msgid "陰陣雨雪" -msgstr "" +msgstr "흐림・소나기 눈/비" #: ./lib/utils/weather_icon.dart:336 msgid "陰有雹" @@ -1183,21 +1313,37 @@ msgstr "맑음・우박" #: ./lib/utils/weather_icon.dart:337 msgid "陰有雷雨" -msgstr "" +msgstr "흐림・뇌우" #: ./lib/utils/weather_icon.dart:338 msgid "陰有雷雪" -msgstr "" +msgstr "흐림・천둥/눈" #: ./lib/utils/weather_icon.dart:339 msgid "陰有雷雹" -msgstr "" +msgstr "흐림・천둥/우박" #: ./lib/utils/weather_icon.dart:340 msgid "陰大雷雨" -msgstr "" +msgstr "흐림・강한 뇌우" #: ./lib/utils/weather_icon.dart:341 msgid "陰大雷雹" -msgstr "" +msgstr "흐림・강한 천둥/우박" + +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "{city}{cityLevel} {town}{townLevel}" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "{city} {town}" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "{city}{cityLevel}" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "{town}{townLevel}" diff --git a/assets/translations/location_names.csv b/assets/translations/location_names.csv new file mode 100644 index 000000000..7f8df84ee --- /dev/null +++ b/assets/translations/location_names.csv @@ -0,0 +1,371 @@ +"key","zh-Hant","en","ja","ko","ru","vi","zh-Hans" +"連江","連江","Lienchiang","連江","롄장","連江","連江","连江" +"宜蘭","宜蘭","Yilan","宜蘭","이란","宜蘭","宜蘭","宜兰" +"彰化","彰化","Changhua","彰化","장화","彰化","彰化","彰化" +"南投","南投","Nantou","南投","난터우","南投","南投","南投" +"雲林","雲林","Yunlin","雲林","윈린","雲林","雲林","云林" +"屏東","屏東","Pingdong","屏東","핑둥","屏東","屏東","屏东" +"基隆","基隆","Keelung","基隆","지룽","基隆","基隆","基隆" +"臺北","臺北","Taipei","台北","타이베이","臺北","臺北","台北" +"新北","新北","New Taipei","新北","신베이","新北","新北","新北" +"臺南","臺南","Tainan","台南","타이난","臺南","臺南","台南" +"桃園","桃園","Taoyuan","桃園","타오위안","桃園","桃園","桃园" +"嘉義","嘉義","Chiayi","嘉義","자이","嘉義","嘉義","嘉义" +"金門","金門","Kinmen","金門","진먼","金門","金門","金门" +"高雄","高雄","Kaohsiung","高雄","가오슝","高雄","高雄","高雄" +"臺東","臺東","Taitung","台東","타이둥","臺東","臺東","台东" +"花蓮","花蓮","Hualien","花蓮","화롄","花蓮","花蓮","花莲" +"澎湖","澎湖","Penghu","澎湖","펑후","澎湖","澎湖","澎湖" +"新竹","新竹","Hsinchu","新竹","신주","新竹","新竹","新竹" +"臺中","臺中","Taichung","台中","타이중","臺中","臺中","台中" +"苗栗","苗栗","Miaoli","苗栗","먀오리","苗栗","苗栗","苗栗" +"成功","成功","Chenggong","成功","成功","成功","成功","成功" +"佳冬","佳冬","Jiadong","佳冬","佳冬","佳冬","佳冬","佳冬" +"麥寮","麥寮","Mailiao","麦寮","麥寮","麥寮","麥寮","麦寮" +"綠島","綠島","Ludao","緑島","綠島","綠島","綠島","绿岛" +"蘭嶼","蘭嶼","Lanyu","蘭嶼","蘭嶼","蘭嶼","蘭嶼","兰屿" +"田中","田中","Tianzhong","田中","田中","田中","田中","田中" +"社頭","社頭","Shetou","社頭","社頭","社頭","社頭","社头" +"竹田","竹田","Zhutian","竹田","竹田","竹田","竹田","竹田" +"萬丹","萬丹","Wandan","万丹","萬丹","萬丹","萬丹","万丹" +"三灣","三灣","Sanwan","三湾","三灣","三灣","三灣","三湾" +"峨眉","峨眉","Emei","峨眉","峨眉","峨眉","峨眉","峨眉" +"南庄","南庄","Nanzhuang","南庄","南庄","南庄","南庄","南庄" +"太保","太保","Taibao","太保","太保","太保","太保","太保" +"中埔","中埔","Zhongpu","中埔","中埔","中埔","中埔","中埔" +"番路","番路","Fanlu","番路","番路","番路","番路","番路" +"水上","水上","Shuishang","水上","水上","水上","水上","水上" +"員林","員林","Yuanlin","員林","員林","員林","員林","员林" +"小港","小港","Xiaogang","小港","小港","小港","小港","小港" +"蘇澳","蘇澳","Suao","蘇澳","蘇澳","蘇澳","蘇澳","苏澳" +"五結","五結","Wujie","五結","五結","五結","五結","五结" +"壯圍","壯圍","Jhuangwei","壮囲","壯圍","壯圍","壯圍","壮围" +"南竿","南竿","Nangan","南竿","南竿","南竿","南竿","南竿" +"莒光","莒光","Juguang","莒光","莒光","莒光","莒光","莒光" +"烏坵","烏坵","Wuqiu","烏坵","烏坵","烏坵","烏坵","乌坵" +"羅東","羅東","Luodong","羅東","羅東","羅東","羅東","罗东" +"員山","員山","Yuanshan","員山","員山","員山","員山","员山" +"冬山","冬山","Dongshan","冬山","冬山","冬山","冬山","冬山" +"三星","三星","Sanxing","三星","三星","三星","三星","三星" +"大同","大同","Datong","大同","大同","大同","大同","大同" +"竹東","竹東","Zhudong","竹東","竹東","竹東","竹東","竹东" +"新埔","新埔","Sinpu","新埔","新埔","新埔","新埔","新埔" +"關西","關西","Guanxi","関西","關西","關西","關西","关西" +"湖口","湖口","Hukou","湖口","湖口","湖口","湖口","湖口" +"芎林","芎林","Qionglin","芎林","芎林","芎林","芎林","芎林" +"橫山","橫山","Hengshan","横山","橫山","橫山","橫山","横山" +"北埔","北埔","Beipu","北埔","北埔","北埔","北埔","北埔" +"五峰","五峰","Wufeng","五峰","五峰","五峰","五峰","五峰" +"龍井","龍井","Longjing","龍井","룽징","龍井","龍井","龙井" +"大雅","大雅","Daya","大雅","다야","大雅","大雅","大雅" +"沙鹿","沙鹿","Shalu","沙鹿","사루","沙鹿","沙鹿","沙鹿" +"梧棲","梧棲","Wuqi","梧棲","우치","梧棲","梧棲","梧栖" +"湖西","湖西","Husi","湖西","湖西","湖西","湖西","湖西" +"金峰","金峰","Jinfeng","金峰","金峰","金峰","金峰","金峰" +"太麻里","太麻里","Taimali","太麻里","太麻里","太麻里","太麻里","太麻里" +"卓蘭","卓蘭","Zhuolan","卓蘭","卓蘭","卓蘭","卓蘭","卓兰" +"大湖","大湖","Dahu","大湖","大湖","大湖","大湖","大湖" +"公館","公館","Gongguan","公館","公館","公館","公館","公馆" +"銅鑼","銅鑼","Tongluo","銅鑼","銅鑼","銅鑼","銅鑼","铜锣" +"頭屋","頭屋","Touwu","頭屋","頭屋","頭屋","頭屋","头屋" +"三義","三義","Sanyi","三義","三義","三義","三義","三义" +"西湖","西湖","Xihu","西湖","西湖","西湖","西湖","西湖" +"造橋","造橋","Zaoqiao","造橋","造橋","造橋","造橋","造桥" +"獅潭","獅潭","Shitan","獅潭","獅潭","獅潭","獅潭","狮潭" +"和美","和美","Hemei","和美","和美","和美","和美","和美" +"線西","線西","Xianxi","線西","線西","線西","線西","线西" +"伸港","伸港","Shenggang","伸港","伸港","伸港","伸港","伸港" +"秀水","秀水","Xiushui","秀水","秀水","秀水","秀水","秀水" +"花壇","花壇","Huatan","花壇","花壇","花壇","花壇","花坛" +"芬園","芬園","Fenyuan","芬園","芬園","芬園","芬園","芬园" +"溪湖","溪湖","Xihu","渓湖","溪湖","溪湖","溪湖","溪湖" +"東石","東石","Dongshi","東石","東石","東石","東石","东石" +"大村","大村","Dacun","大村","大村","大村","大村","大村" +"埔鹽","埔鹽","Puyan","埔塩","埔鹽","埔鹽","埔鹽","埔盐" +"埔心","埔心","Puxin","埔心","埔心","埔心","埔心","埔心" +"永靖","永靖","Yongjing ","永靖","永靖","永靖","永靖","永靖" +"二水","二水","Ershui","二水","二水","二水","二水","二水" +"二林","二林","Erlin","二林","二林","二林","二林","二林" +"埤頭","埤頭","Pitou","埤頭","埤頭","埤頭","埤頭","埤头" +"芳苑","芳苑","Fangyuan","芳苑","芳苑","芳苑","芳苑","芳苑" +"大城","大城","Dacheng","大城","大城","大城","大城","大城" +"竹塘","竹塘","Zhutang","竹塘","竹塘","竹塘","竹塘","竹塘" +"溪州","溪州","Xizhou","渓州","溪州","溪州","溪州","溪洲" +"埔里","埔里","Puli","埔里","埔里","埔里","埔里","埔里" +"草屯","草屯","Caotun","草屯","草屯","草屯","草屯","草屯" +"竹山","竹山","Zhushan","竹山","竹山","竹山","竹山","竹山" +"集集","集集","Jiji","集集","集集","集集","集集","集集" +"名間","名間","Mingjian","名間","名間","名間","名間","名间" +"鹿谷","鹿谷","Lugu","鹿谷","鹿谷","鹿谷","鹿谷","鹿谷" +"中寮","中寮","Zhongliao","中寮","中寮","中寮","中寮","中寮" +"魚池","魚池","Yuchi","魚池","魚池","魚池","魚池","鱼池" +"國姓","國姓","Guoxing","国姓","國姓","國姓","國姓","国姓" +"水里","水里","Shuili","水里","水里","水里","水里","水里" +"信義","信義","Xinyi","信義","信義","信義","信義","信义" +"仁愛","仁愛","Ren'Ai","仁愛","仁愛","仁愛","仁愛","仁爱" +"斗六","斗六","Douliu","斗六","斗六","斗六","斗六","斗六" +"斗南","斗南","Dounan","斗南","斗南","斗南","斗南","鬥南" +"虎尾","虎尾","Huwei","虎尾","虎尾","虎尾","虎尾","虎尾" +"西螺","西螺","Xiluo","西螺","西螺","西螺","西螺","西螺" +"土庫","土庫","Tuku","土庫","土庫","土庫","土庫","土库" +"北港","北港","Beigang","北港","北港","北港","北港","北港" +"古坑","古坑","Gukeng","古坑","古坑","古坑","古坑","古坑" +"大埤","大埤","Dapi","大埤","大埤","大埤","大埤","大埤" +"莿桐","莿桐","Citong","莿桐","莿桐","莿桐","莿桐","莿桐" +"林內","林內","Linnei","林内","林內","林內","林內","林內" +"二崙","二崙","Erlun","二崙","二崙","二崙","二崙","二仑" +"崙背","崙背","Lunbei","崙背","崙背","崙背","崙背","仑背" +"東勢","東勢","Dongshi","東勢","둥스","東勢","東勢","东势" +"褒忠","褒忠","Baozhong","褒忠","褒忠","褒忠","褒忠","褒忠" +"元長","元長","Yuanchang","元長","元長","元長","元長","元长" +"水林","水林","Shuilin","水林","水林","水林","水林","水林" +"朴子","朴子","Puzi","朴子","朴子","朴子","朴子","朴子" +"大林","大林","Dalin","大林","大林","大林","大林","大林" +"民雄","民雄","Minxiong","民雄","民雄","民雄","民雄","民雄" +"溪口","溪口","Xikou","渓口","溪口","溪口","溪口","溪口" +"新港","新港","Xingang","新港","新港","新港","新港","新港" +"六腳","六腳","Liujiao","六脚","六腳","六腳","六腳","六脚" +"義竹","義竹","Yizhu","義竹","義竹","義竹","義竹","义竹" +"鹿草","鹿草","Lucao","鹿草","鹿草","鹿草","鹿草","鹿草" +"竹崎","竹崎","Zhuqi","竹崎","竹崎","竹崎","竹崎","竹崎" +"梅山","梅山","Meishan","梅山","梅山","梅山","梅山","梅山" +"大埔","大埔","Dapu","大埔","大埔","大埔","大埔","大埔" +"阿里山","阿里山","Alishan","阿里山","阿里山","阿里山","阿里山","阿里山" +"潮州","潮州","Chaojhou","潮州","潮州","潮州","潮州","潮州" +"長治","長治","Changzhi","長治","長治","長治","長治","长治" +"麟洛","麟洛","Linluo","麟洛","麟洛","麟洛","麟洛","麟洛" +"九如","九如","Jiuru","九如","九如","九如","九如","九如" +"里港","里港","Ligang","里港","里港","里港","里港","里港" +"鹽埔","鹽埔","Yanpuxinwei","塩埔","鹽埔","鹽埔","鹽埔","盐埔" +"高樹","高樹","Gaoshu","高樹","高樹","高樹","高樹","高树" +"萬巒","萬巒","Wanluan","万巒","萬巒","萬巒","萬巒","万峦" +"內埔","內埔","Neipu","内埔","內埔","內埔","內埔","内埔" +"新埤","新埤","Xinpi","新埤","新埤","新埤","新埤","新埤" +"崁頂","崁頂","Kanding","崁頂","崁頂","崁頂","崁頂","崁顶" +"南州","南州","Nanzhou","南州","南州","南州","南州","南州" +"琉球","琉球","Liuqiu","琉球","琉球","琉球","琉球","琉球" +"三地門","三地門","Sandimen","三地門","三地門","三地門","三地門","三地门" +"霧臺","霧臺","Wutai","霧台","霧臺","霧臺","霧臺","雾台" +"瑪家","瑪家","Majia","瑪家","瑪家","瑪家","瑪家","玛家" +"泰武","泰武","Taiwu","泰武","泰武","泰武","泰武","泰武" +"來義","來義","Laiyi","来義","來義","來義","來義","来义" +"春日","春日","Chunri","春日","春日","春日","春日","春日" +"獅子","獅子","Shizi","獅子","獅子","獅子","獅子","狮子" +"鹿野","鹿野","Luye","鹿野","鹿野","鹿野","鹿野","鹿野" +"池上","池上","Chihshang","池上","池上","池上","池上","池上" +"延平","延平","Yanping","延平","延平","延平","延平","延平" +"光復","光復","Guangfu","光復","光復","光復","光復","光复" +"瑞穗","瑞穗","Ruisui","瑞穂","瑞穗","瑞穗","瑞穗","瑞穗" +"富里","富里","Fuli","富里","富里","富里","富里","富里" +"馬公","馬公","Magong","馬公","馬公","馬公","馬公","马公" +"白沙","白沙","Baisha","白沙","白沙","白沙","白沙","白沙" +"西嶼","西嶼","Xiyu","西嶼","西嶼","西嶼","西嶼","西屿" +"望安","望安","Wangan","望安","望安","望安","望安","望安" +"七美","七美","Qimei","七美","七美","七美","七美","七美" +"暖暖","暖暖","Nuannuan","暖暖","暖暖","暖暖","暖暖","暖暖" +"大安","大安","Da-An","大安","다안","大安","大安","大安" +"文山","文山","Wenshan","文山","文山","文山","文山","文山" +"鹽埕","鹽埕","Yancheng","塩埕","鹽埕","鹽埕","鹽埕","盐埕" +"新興","新興","Sinsing","新興","新興","新興","新興","新兴" +"前金","前金","Qianjin","前金","前金","前金","前金","前金" +"前鎮","前鎮","Chian Jhen","前鎮","前鎮","前鎮","前鎮","前镇" +"頭城","頭城","Toucheng","頭城","頭城","頭城","頭城","头城" +"南澳","南澳","Nanao","南澳","南澳","南澳","南澳","南澳" +"竹北","竹北","Zhubei","竹北","竹北","竹北","竹北","竹北" +"新豐","新豐","Sinfong","新豊","新豐","新豐","新豐","新丰" +"苑裡","苑裡","Yuanli","苑裡","苑裡","苑裡","苑裡","苑里" +"通霄","通霄","Tongxiao","通霄","通霄","通霄","通霄","通宵" +"竹南","竹南","Jhunan","竹南","竹南","竹南","竹南","竹南" +"後龍","後龍","Houlong","後龍","後龍","後龍","後龍","后龙" +"鹿港","鹿港","Lukang","鹿港","鹿港","鹿港","鹿港","鹿港" +"福興","福興","Fuxing","福興","福興","福興","福興","福兴" +"臺西","臺西","Taixi","台西","臺西","臺西","臺西","台西" +"四湖","四湖","Sihu","四湖","四湖","四湖","四湖","四湖" +"口湖","口湖","Kouhu","口湖","口湖","口湖","口湖","口湖" +"布袋","布袋","Budai","布袋","布袋","布袋","布袋","布袋" +"東港","東港","Donggang","東港","東港","東港","東港","东港" +"枋寮","枋寮","Fangliao","枋寮","枋寮","枋寮","枋寮","枋寮" +"新園","新園","Xinyuan","新園","新園","新園","新園","新园" +"林邊","林邊","Linbian","林辺","林邊","林邊","林邊","林边" +"車城","車城","Checheng","車城","車城","車城","車城","车城" +"滿州","滿州","Manzhou","満州","滿州","滿州","滿州","满州" +"枋山","枋山","Fangshan","枋山","枋山","枋山","枋山","枋山" +"牡丹","牡丹","Mudan","牡丹","牡丹","牡丹","牡丹","牡丹" +"卑南","卑南","Beinan","卑南","卑南","卑南","卑南","卑南" +"東河","東河","Donghe","東河","東河","東河","東河","东河" +"吉安","吉安","Ji'an","吉安","吉安","吉安","吉安","吉安" +"壽豐","壽豐","Shoufeng","寿豊","壽豐","壽豐","壽豐","寿丰" +"秀林","秀林","Xiulin","秀林","秀林","秀林","秀林","秀林" +"楠梓","楠梓","Nanzi","楠梓","楠梓","楠梓","楠梓","楠梓" +"鳳山","鳳山","Fengshan","鳳山","鳳山","鳳山","鳳山","凤山" +"大寮","大寮","Daliao","大寮","大寮","大寮","大寮","大寮" +"大樹","大樹","Dashu","大樹","大樹","大樹","大樹","大树" +"大社","大社","Dashe","大社","大社","大社","大社","大社" +"仁武","仁武","Renwu","仁武","仁武","仁武","仁武","仁武" +"鳥松","鳥松","Niaosong","鳥松","鳥松","鳥松","鳥松","鸟松" +"岡山","岡山","Gangshan","岡山","岡山","岡山","岡山","冈山" +"橋頭","橋頭","Qiaotou","橋頭","橋頭","橋頭","橋頭","桥头" +"燕巢","燕巢","Yanchao","燕巣","燕巢","燕巢","燕巢","燕巢" +"田寮","田寮","Tianliao","田寮","田寮","田寮","田寮","田寮" +"阿蓮","阿蓮","Alian","阿蓮","阿蓮","阿蓮","阿蓮","阿连" +"路竹","路竹","Luzhu","路竹","路竹","路竹","路竹","路竹" +"湖內","湖內","Hunei","湖内","湖內","湖內","湖內","湖内" +"旗山","旗山","Qishan","旗山","旗山","旗山","旗山","旗山" +"美濃","美濃","Meinong","美濃","美濃","美濃","美濃","美浓" +"六龜","六龜","Liugui","六亀","六龜","六龜","六龜","六龟" +"甲仙","甲仙","Jiaxian","甲仙","甲仙","甲仙","甲仙","甲仙" +"杉林","杉林","Shanlin","杉林","杉林","杉林","杉林","杉林" +"內門","內門","Neimen","内門","內門","內門","內門","内门" +"茂林","茂林","Maolin","茂林","茂林","茂林","茂林","茂林" +"桃源","桃源","Taoyuan","桃源","桃源","桃源","桃源","桃源" +"那瑪夏","那瑪夏","Namaxia","那瑪夏","那瑪夏","那瑪夏","那瑪夏","那玛夏" +"永和","永和","Yonghe","永和","永和","永和","永和","永和" +"新店","新店","Xindian","新店","新店","新店","新店","新店" +"土城","土城","Tucheng","土城","土城","土城","土城","土城" +"蘆洲","蘆洲","Lujhou","蘆洲","蘆洲","蘆洲","蘆洲","芦洲" +"五股","五股","Wugu","五股","五股","五股","五股","五股" +"坪林","坪林","Pinglin","坪林","坪林","坪林","坪林","坪林" +"平溪","平溪","Pingxi","平渓","平溪","平溪","平溪","平溪" +"烏來","烏來","Wulai","烏来","烏來","烏來","烏來","乌来" +"豐原","豐原","Fengyuan","豊原","펑위안","豐原","豐原","丰原" +"后里","后里","Houli","后里","허우리","后里","后里","后里" +"神岡","神岡","Shengang","神岡","룽징","神岡","神岡","神冈" +"新社","新社","Xinshe","新社","신서","新社","新社","新社" +"石岡","石岡","Shigang","石岡","스강","石岡","石岡","石冈" +"外埔","外埔","Waipu","外埔","와이푸","外埔","外埔","外埔" +"大肚","大肚","Dadu","大肚","다두","大肚","大肚","大肚" +"新營","新營","Xinying","新営","新營","新營","新營","新营" +"鹽水","鹽水","Yanshui","塩水","鹽水","鹽水","鹽水","盐水" +"白河","白河","Baihe","白河","白河","白河","白河","白河" +"後壁","後壁","Houbi","後壁","後壁","後壁","後壁","后壁" +"麻豆","麻豆","Madou","麻豆","麻豆","麻豆","麻豆","麻豆" +"下營","下營","Xiaying","下営","下營","下營","下營","下营" +"六甲","六甲","Liujia","六甲","六甲","六甲","六甲","六甲" +"官田","官田","Guantian","官田","官田","官田","官田","官田" +"大內","大內","Danei","大内","大內","大內","大內","大内" +"佳里","佳里","Jiali","佳里","佳里","佳里","佳里","佳里" +"學甲","學甲","Xuejia","学甲","學甲","學甲","學甲","学甲" +"西港","西港","Xigang","西港","西港","西港","西港","西港" +"新化","新化","Xinhua","新化","新化","新化","新化","新化" +"新市","新市","Xinshi","新市","新市","新市","新市","新市" +"安定","安定","Anding","安定","安定","安定","安定","安定" +"玉井","玉井","Yujing","玉井","玉井","玉井","玉井","玉井" +"楠西","楠西","Nanxi","楠西","楠西","楠西","楠西","楠西" +"南化","南化","Nanhua","南化","南化","南化","南化","南化" +"左鎮","左鎮","Zuozhen","左鎮","左鎮","左鎮","左鎮","左镇" +"仁德","仁德","Rende","仁徳","仁德","仁德","仁德","仁德" +"歸仁","歸仁","Guiren","帰仁","歸仁","歸仁","歸仁","归仁" +"關廟","關廟","Guanmiao","関廟","關廟","關廟","關廟","关庙" +"龍崎","龍崎","Longqi","龍崎","龍崎","龍崎","龍崎","龙崎" +"永康","永康","Yongkang","永康","永康","永康","永康","永康" +"北","北","North","北","베이","北","北","北" +"林園","林園","Linyuan","林園","林園","林園","林園","林园" +"茄萣","茄萣","Qieding","茄萣","茄萣","茄萣","茄萣","茄萣" +"永安","永安","Yong'An","永安","永安","永安","永安","永安" +"彌陀","彌陀","Mituo","弥陀","彌陀","彌陀","彌陀","弥陀" +"梓官","梓官","Ziguan","梓官","梓官","梓官","梓官","梓官" +"淡水","淡水","Tamsui","淡水","淡水","淡水","淡水","淡水" +"瑞芳","瑞芳","Rueifang","瑞芳","瑞芳","瑞芳","瑞芳","瑞芳" +"林口","林口","Linkou","林口","林口","林口","林口","林口" +"三芝","三芝","Sanzhi","三芝","三芝","三芝","三芝","三芝" +"八里","八里","Bali","八里","八里","八里","八里","八里" +"大甲","大甲","Dajia","大甲","다자","大甲","大甲","大甲" +"北門","北門","Beimen","北門","北門","北門","北門","北门" +"安南","安南","Annan","安南","安南","安南","安南","安南" +"蘆竹","蘆竹","Luzhu","蘆竹","蘆竹","蘆竹","蘆竹","芦竹" +"龜山","龜山","Guishan","亀山","龜山","龜山","龜山","龟山" +"復興","復興","Fuxing","復興","復興","復興","復興","复兴" +"東","東","East","東","둥","東","東","东" +"西","西","West","西","시","西","西","西" +"達仁","達仁","Daren","達仁","達仁","達仁","達仁","达仁" +"大武","大武","Dawu","大武","大武","大武","大武","大武" +"關山","關山","Guanshan","関山","關山","關山","關山","关山" +"海端","海端","Haiduan","海端","海端","海端","海端","海端" +"香山","香山","Xiangshan","香山","香山","香山","香山","香山" +"礁溪","礁溪","Chiaoshi","礁渓","礁溪","礁溪","礁溪","礁溪" +"玉里","玉里","Yuli","玉里","玉里","玉里","玉里","玉里" +"卓溪","卓溪","Zhuoxi","卓渓","卓溪","卓溪","卓溪","卓溪" +"頭份","頭份","Toufen","頭份","頭份","頭份","頭份","头份" +"清水","清水","Qingshui","清水","清水","清水","清水","清水" +"南","南","South","南","난","南","南","南" +"安平","安平","Anping","安平","安平","安平","安平","安平" +"中西","中西","West Central","中西","中西","中西","中西","中西" +"大溪","大溪","Dasi","大渓","大溪","大溪","大溪","大溪" +"八德","八德","Bade","八徳","八德","八德","八德","八德" +"大園","大園","Dayuan","大園","大園","大園","大園","大园" +"楊梅","楊梅","Yangmei","楊梅","楊梅","楊梅","楊梅","杨梅" +"七堵","七堵","Qidu","七堵","七堵","七堵","七堵","七堵" +"中正","中正","Zhongzheng","中正","中正","中正","中正","中正" +"中山","中山","Zhongshan","中山","中山","中山","中山","中山" +"安樂","安樂","Anle","安楽","安樂","安樂","安樂","安乐" +"三峽","三峽","Sanshia","三峡","三峽","三峽","三峽","三峡" +"鶯歌","鶯歌","Yingge","鶯歌","鶯歌","鶯歌","鶯歌","莺歌" +"中和","中和","Zhonghe","中和","中和","中和","中和","中和" +"樹林","樹林","Shulin","樹林","樹林","樹林","樹林","树林" +"深坑","深坑","Shenkeng","深坑","深坑","深坑","深坑","深坑" +"板橋","板橋","Banchiao","板橋","板橋","板橋","板橋","板桥" +"石碇","石碇","Shihding","石碇","石碇","石碇","石碇","石碇" +"新莊","新莊","Xinzhuang","新荘","新莊","新莊","新莊","新庄" +"泰山","泰山","Taishan","泰山","泰山","泰山","泰山","泰山" +"三重","三重","Sanchong","三重","三重","三重","三重","三重" +"雙溪","雙溪","Shuangsi","双渓","雙溪","雙溪","雙溪","双溪" +"貢寮","貢寮","Gongliao","貢寮","貢寮","貢寮","貢寮","贡寮" +"汐止","汐止","Xizhi","汐止","汐止","汐止","汐止","汐止" +"萬里","萬里","Wanli","万里","萬里","萬里","萬里","万里" +"金山","金山","Jinshan","金山","金山","金山","金山","金山" +"石門","石門","Shimen","石門","石門","石門","石門","石门" +"苓雅","苓雅","Lingya","苓雅","苓雅","苓雅","苓雅","苓雅" +"三民","三民","Sanmin","三民","三民","三民","三民","三民" +"新屋","新屋","Xinwu","新屋","新屋","新屋","新屋","新屋" +"觀音","觀音","Guanyin","観音","觀音","觀音","觀音","观音" +"北竿","北竿","Beigan","北竿","北竿","北竿","北竿","北竿" +"東引","東引","Dongyin","東引","東引","東引","東引","东引" +"烈嶼","烈嶼","Lieyu","烈嶼","烈嶼","烈嶼","烈嶼","烈屿" +"旗津","旗津","Qijin","旗津","旗津","旗津","旗津","旗津" +"長濱","長濱","Changbin","長浜","長濱","長濱","長濱","长滨" +"豐濱","豐濱","Fengbin","豊浜","豐濱","豐濱","豐濱","丰滨" +"霧峰","霧峰","Wufeng","霧峰","우펑","霧峰","霧峰","雾峰" +"大里","大里","Dali","大里","다리","大里","大里","大里" +"烏日","烏日","Wuri","烏日","우르","烏日","烏日","乌日" +"中","中","Central","中","중","中","中","中" +"南屯","南屯","Nantun","南屯","난툰","南屯","南屯","南屯" +"西屯","西屯","Xitun","西屯","시툰","西屯","西屯","西屯" +"北屯","北屯","Beitun","北屯","베이툰","北屯","北屯","北屯" +"潭子","潭子","Tanzi","潭子","탄쯔","潭子","潭子","潭子" +"萬華","萬華","Wanhua","万華","萬華","萬華","萬華","万华" +"松山","松山","Songshan","松山","松山","松山","松山","松山" +"士林","士林","Shilin","士林","士林","士林","士林","士林" +"北投","北投","Beitou","北投","北投","北投","北投","北投" +"新城","新城","Xincheng","新城","新城","新城","新城","新城" +"善化","善化","Shanhua","善化","善化","善化","善化","善化" +"山上","山上","Shanshang","山上","山上","山上","山上","山上" +"北斗","北斗","Beidou","北斗","北斗","北斗","北斗","北斗" +"田尾","田尾","Tianwei","田尾","田尾","田尾","田尾","田尾" +"金沙","金沙","Jinsha ","金沙","金沙","金沙","金沙","金沙" +"金湖","金湖","Jinhu","金湖","金湖","金湖","金湖","金湖" +"柳營","柳營","Liuying","柳営","柳營","柳營","柳營","柳营" +"東山","東山","Dongshan","東山","東山","東山","東山","东山" +"七股","七股","Qigu","七股","七股","七股","七股","七股" +"將軍","將軍","Jiangjun","将軍","將軍","將軍","將軍","将军" +"鼓山","鼓山","Gushan","鼓山","鼓山","鼓山","鼓山","鼓山" +"左營","左營","Zuoying","左営","左營","左營","左營","左营" +"中壢","中壢","Zhongli","中壢","中壢","中壢","中壢","中坜" +"寶山","寶山","Baoshan","宝山","寶山","寶山","寶山","宝山" +"恆春","恆春","Hengchun","恒春","恆春","恆春","恆春","恒春" +"太平","太平","Taiping","太平","太平","太平","太平","太平" +"鳳林","鳳林","Fenglin","鳳林","鳳林","鳳林","鳳林","凤林" +"萬榮","萬榮","Wanrong","万栄","萬榮","萬榮","萬榮","万荣" +"龍潭","龍潭","Longtan","龍潭","龍潭","龍潭","龍潭","龙潭" +"平鎮","平鎮","Pingjhen","平鎮","平鎮","平鎮","平鎮","平镇" +"南港","南港","Nangang","南港","南港","南港","南港","南港" +"內湖","內湖","Neihu","内湖","內湖","內湖","內湖","内湖" +"金寧","金寧","Jinning","金寧","金寧","金寧","金寧","金宁" +"金城","金城","Jincheng","金城","金城","金城","金城","金城" +"尖石","尖石","Jianshi","尖石","尖石","尖石","尖石","尖石" +"泰安","泰安","Tai-An","泰安","泰安","泰安","泰安","泰安" +"和平","和平","Heping","和平","허핑","和平","和平","和平" +"縣","縣","County","県","현","縣","縣","县" +"鄉","鄉","Township","郷","향","鄉","鄉","乡" +"鎮","鎮","Town","鎮","진","鎮","鎮","镇" +"市","市","City","市","시","市","市","市" +"區","區","District","区","구","區","區","区" diff --git a/assets/translations/ru.po b/assets/translations/ru.po index 04b222f55..6f61915ca 100644 --- a/assets/translations/ru.po +++ b/assets/translations/ru.po @@ -4,18 +4,22 @@ msgstr "" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: ru\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" -"X-Crowdin-File-ID: 20\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 26\n" "Project-Id-Version: dpip\n" "Content-Type: text/plain; charset=UTF-8\n" "Language-Team: Russian\n" "Language: ru_RU\n" -"PO-Revision-Date: 2025-07-23 03:45\n" +"PO-Revision-Date: 2025-09-01 03:16\n" -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "" +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "" + #: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "" @@ -28,23 +32,23 @@ msgstr "" msgid "單位" msgstr "" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "" @@ -61,10 +65,10 @@ msgid "天氣警特報" msgstr "" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" +msgid "防災資訊" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" msgstr "" @@ -80,11 +84,11 @@ msgstr "" msgid "設定" msgstr "" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "" @@ -92,23 +96,23 @@ msgstr "" msgid "接收類別" msgstr "" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" msgstr "" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" msgstr "" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" msgstr "" @@ -120,7 +124,7 @@ msgstr "" msgid "發送公告時" msgstr "" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" msgstr "" @@ -132,7 +136,7 @@ msgstr "" msgid "地震速報" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "" @@ -140,7 +144,7 @@ msgstr "" msgid "天氣" msgstr "" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "" @@ -148,22 +152,20 @@ msgstr "" msgid "其他" msgstr "" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "海嘯警報發布時\n" -"沿海地區鄉鎮" +msgid "海嘯警報發布時" msgstr "" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "海嘯警報發布時\n" -"上述除外地區" +msgid "海嘯消息發布時" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 @@ -274,11 +276,11 @@ msgid "所在地(鄉鎮)預估震度 1 以上" msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" +msgid "所在地(鄉鎮)發布防災警訊時" msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" +msgid "所在地(鄉鎮)發布防災資訊時" msgstr "" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 @@ -292,8 +294,11 @@ msgid "所在地(鄉鎮)發布上述除外燈號之\n" msgstr "" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" msgstr "" #: ./lib/app/settings/unit/page.dart:28 @@ -332,60 +337,60 @@ msgstr "Переведено {translated}・Утверждено {approved}" msgid "來源語言" msgstr "" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "" -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" msgstr "" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" msgstr "" -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" msgstr "" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" msgstr "" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" msgstr "" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "" @@ -469,51 +474,163 @@ msgstr "" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "" -#: ./lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "" -#: ./lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "" -#: ./lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "" -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" msgstr "" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" msgstr "" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" msgstr "" -#: ./lib/app/settings/location/select/page.dart:26 -msgid "縣市" +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" msgstr "" #: ./lib/app/settings/location/select/page.dart:38 +msgid "縣市" +msgstr "" + +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" msgstr "" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "" + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" msgstr "" @@ -545,10 +662,6 @@ msgstr "" msgid "使用系統顏色" msgstr "" -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "" - #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "" @@ -561,8 +674,8 @@ msgstr "" msgid "服務區域外,僅在臺灣各地可用" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" msgstr "" #: ./lib/app/home/_widgets/weather_header.dart:127 @@ -573,31 +686,39 @@ msgstr "" msgid "尚未設定所在地" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:874 +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1089 msgid "第 {serial} 報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" msgstr "" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" msgstr "" @@ -613,7 +734,7 @@ msgstr "" msgid "重試" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "" @@ -665,19 +786,15 @@ msgstr "" msgid "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "" @@ -685,175 +802,191 @@ msgstr "" msgid "儲存" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "" -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "" - -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" msgstr "" -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "" - -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "" @@ -913,10 +1046,6 @@ msgstr "" msgid "公告詳情" msgstr "" -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "" - #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" msgstr "" @@ -1201,3 +1330,19 @@ msgstr "" msgid "陰大雷雹" msgstr "" +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "" + diff --git a/assets/translations/vi.po b/assets/translations/vi.po index 76601b952..ad1a067f7 100644 --- a/assets/translations/vi.po +++ b/assets/translations/vi.po @@ -4,18 +4,22 @@ msgstr "" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: vi\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" -"X-Crowdin-File-ID: 20\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 26\n" "Project-Id-Version: dpip\n" "Content-Type: text/plain; charset=UTF-8\n" "Language-Team: Vietnamese\n" "Language: vi_VN\n" -"PO-Revision-Date: 2025-07-23 03:45\n" +"PO-Revision-Date: 2025-09-01 03:16\n" -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "Vị Trí Hiện Tại" +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "" + #: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "" @@ -28,23 +32,23 @@ msgstr "Ngôn ngữ" msgid "單位" msgstr "" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "Bản đồ" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "Thông báo đẩy" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "Cảnh báo động đất sớm" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" msgstr "giám sát động đất" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "Báo cáo động đất" @@ -61,10 +65,10 @@ msgid "天氣警特報" msgstr "Cảnh báo thời tiết" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" -msgstr "Thông tin di tản" +msgid "防災資訊" +msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" msgstr "Thông tin sóng thần" @@ -80,11 +84,11 @@ msgstr "quyên tặng" msgid "設定" msgstr "Cài đặt" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "" @@ -92,23 +96,23 @@ msgstr "" msgid "接收類別" msgstr "" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" msgstr "Cường độ tại địa phương từ 1 trở lên" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" msgstr "" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" msgstr "Cường độ tại địa phương từ 4 trở lên" @@ -120,7 +124,7 @@ msgstr "Kiểm tra âm thanh" msgid "發送公告時" msgstr "Khi gửi thông báo" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" msgstr "" @@ -132,7 +136,7 @@ msgstr "" msgid "地震速報" msgstr "Cảnh báo động đất sớm" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "" @@ -140,7 +144,7 @@ msgstr "" msgid "天氣" msgstr "" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "" @@ -148,25 +152,21 @@ msgstr "" msgid "其他" msgstr "Khác" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "海嘯警報發布時\n" -"沿海地區鄉鎮" -msgstr "Khi phát hành cảnh báo sóng thần\n" -"các xã, thị trấn ven biển" +msgid "海嘯警報發布時" +msgstr "" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "Nói chung" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "海嘯警報發布時\n" -"上述除外地區" -msgstr "Khi cảnh báo sóng thần được ban hành.\n" -"Các khu vực bị loại trừ khỏi các mục trên." +msgid "海嘯消息發布時" +msgstr "" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息(無聲通知)" @@ -279,12 +279,12 @@ msgid "所在地(鄉鎮)預估震度 1 以上" msgstr "Dự đoán cường độ tại địa phương (thị trấn) từ 1 trở lên" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" -msgstr "Khi khu vực địa phương (thị trấn) ban hành cảnh báo sơ tán" +msgid "所在地(鄉鎮)發布防災警訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" -msgstr "Khi khu vực địa phương (thị trấn) thông báo thông tin sơ tán" +msgid "所在地(鄉鎮)發布防災資訊時" +msgstr "" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 msgid "所在地(鄉鎮)發布紅色燈號之\n" @@ -297,8 +297,11 @@ msgid "所在地(鄉鎮)發布上述除外燈號之\n" msgstr "Khu vực địa phương (thị trấn) ban hành báo cáo đặc biệt cảnh báo thời tiết tín hiệu" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" msgstr "" #: ./lib/app/settings/unit/page.dart:28 @@ -337,60 +340,60 @@ msgstr "Đã dịch {translated}・Đã hiệu đính {approved}" msgid "來源語言" msgstr "Ngôn ngữ nguồn" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "Không thể tải nhật ký thay đổi, vui lòng thử lại sau." -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" msgstr "" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" msgstr "" -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" msgstr "" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" msgstr "" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" msgstr "" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" msgstr "" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "Vị trí" @@ -474,51 +477,163 @@ msgstr "Nhật ký ứng dụng" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "Tất cả thông tin phải tuân theo nội dung do Đài Loan Cơ quan Thời tiết Trung ương (CWA) công bố." -#: ./lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "Chế độ nguồn điện thấp" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "Hủy bỏ" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "Cập nhật tự động" -#: ./lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "Cập nhật vị trí hiện tại định kỳ" -#: ./lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "Tính năng định vị tự động sẽ sử dụng GPS trên thiết bị của bạn để tự động cập nhật vị trí của bạn dựa trên vị trí địa lý, cung cấp thông tin thời tiết và động đất theo thời gian thực, giúp bạn luôn nắm bắt được tình hình mới nhất tại địa phương." -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" -msgstr "Thành phố trực thuộc trung ương/Tỉnh thành" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" -msgstr "Chưa đặt" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" +msgstr "" + +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" +msgstr "" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" -msgstr "Quận/Phường/Xã" +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" +msgstr "" -#: ./lib/app/settings/location/select/page.dart:26 +#: ./lib/app/settings/location/select/page.dart:38 msgid "縣市" msgstr "Quận" -#: ./lib/app/settings/location/select/page.dart:38 +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "Hình ảnh radar" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "Nhiệt độ" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "Lượng mưa" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "Hướng gió/Tốc độ gió" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" msgstr "" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "" + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" msgstr "" @@ -550,10 +665,6 @@ msgstr "" msgid "使用系統顏色" msgstr "" -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "Hủy bỏ" - #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "Xác nhận" @@ -566,9 +677,9 @@ msgstr "Khu vực gần bạn đang có mưa giông hoặc mưa lớn. Vui lòng msgid "服務區域外,僅在臺灣各地可用" msgstr "Ngoài khu vực dịch vụ, chỉ có sẵn ở các địa điểm khác nhau trên khắp Đài Loan." -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" -msgstr "Hình ảnh radar" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" +msgstr "Chưa đặt" #: ./lib/app/home/_widgets/weather_header.dart:127 msgid "體感約 {apparent}°" @@ -578,31 +689,39 @@ msgstr "" msgid "尚未設定所在地" msgstr "Bạn chưa thiết lập vị trí của mình" -#: ./lib/app/map/_lib/managers/monitor.dart:874 +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1089 msgid "第 {serial} 報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" msgstr "" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" msgstr "" @@ -618,7 +737,7 @@ msgstr "Không thể tải nhật ký thay đổi, vui lòng thử lại sau." msgid "重試" msgstr "Thử lại" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "Tiếp theo" @@ -670,19 +789,15 @@ msgstr "Chào mừng đến với DPIP" msgid "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "DPIP là ứng dụng được thiết kế bởi một nhóm địa phương tại Đài Loan, tích hợp thông tin từ TREM-Net (Mạng quan sát động đất thời gian thực Đài Loan) và dữ liệu từ Đài Loan Cơ quan thời tiết trung ương (CWA) để cung cấp một ứng dụng thông tin phòng chống thiên tai tích hợp, duy nhất và tiện lợi." -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "Dịch vụ được sử dụng để gửi thông báo cảnh báo thiên tai khẩn cấp" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" msgstr "Dịch vụ được sử dụng để cập nhật vị trí và cung cấp thông tin cảnh báo tại khu vực hiện tại" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "Chế độ nguồn điện thấp" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "Cho phép DPIP tiếp tục hoạt động ở chế độ nền để thông báo phòng ngừa thảm họa ngay lập tức." @@ -690,175 +805,191 @@ msgstr "Cho phép DPIP tiếp tục hoạt động ở chế độ nền để t msgid "儲存" msgstr "Lưu trữ hình" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "Để lưu trữ hình ảnh trực quan dữ liệu từ Đài Loan Cơ quan thời tiết trung ương (CWA) hoặc ExpTech." -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "Yêu cầu để xin phép" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "Người dùng cần phải tự tay vào trang cài đặt để mở các quyền có liên quan." -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "Sự cho phép" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "Chúng tôi luôn ủng hộ người dùng và nỗ lực không ngừng vì quyền riêng tư của họ." -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" msgstr "" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "" -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "Nhiệt độ" - -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "Lượng mưa" - -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "Hướng gió/Tốc độ gió" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" +msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" msgstr "" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" msgstr "" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "Hôm nay" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" msgstr "10 phút" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" msgstr "1 giờ" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" msgstr "3 giờ" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" msgstr "6 giờ" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" msgstr "12 giờ" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" msgstr "24 giờ" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" msgstr "2 ngày" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" msgstr "3 ngày" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" +msgstr "" + +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "Thêm" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" msgstr "" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "Động đất nhẹ, cảm nhận được ở khu vực nhỏ" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "Cường độ" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "Độ sâu chấn tiêu" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "Trang báo cáo" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" msgstr "Ngày giờ nhận biết động đất" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "nằm ở" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "Cường độ địa chấn tại các khu vực" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "Bản đồ báo cáo động đất" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "Bản đồ cường độ địa chấn" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "Bản đồ gia tốc mặt đất tối đa" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "Bản đồ vận tốc mặt đất tối đa" @@ -918,10 +1049,6 @@ msgstr "" msgid "公告詳情" msgstr "" -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "" - #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" msgstr "" @@ -1206,3 +1333,19 @@ msgstr "" msgid "陰大雷雹" msgstr "" +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "{city}{cityLevel} {town}{townLevel}" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "{city} {town}" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "{city}{cityLevel}" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "{town}{townLevel}" + diff --git a/assets/translations/weather_station_names.csv b/assets/translations/weather_station_names.csv new file mode 100644 index 000000000..3f35d3d58 --- /dev/null +++ b/assets/translations/weather_station_names.csv @@ -0,0 +1,819 @@ +"key","zh-Hant","en","ja","ko","ru","vi","zh-Hans" +"466850","五分山雷達站","Wufenshan","五分山レーダー局","五分山雷達站","五分山雷達站","五分山雷達站","五分山雷达站" +"466881","新北","New Taipei","新北","신베이","新北","新北","新北" +"466900","淡水","Tamsui","淡水","淡水","淡水","淡水","淡水" +"466910","鞍部","Anbu","鞍部","鞍部","鞍部","鞍部","鞍部" +"466920","臺北","Taipei","台北","타이베이","臺北","臺北","台北" +"466930","竹子湖","Zhuzihu","竹子湖","竹子湖","竹子湖","竹子湖","竹子湖" +"466940","基隆","Keelung","基隆","지룽","基隆","基隆","基隆" +"466950","彭佳嶼","Pengjiayu","彭佳嶼","彭佳嶼","彭佳嶼","彭佳嶼","彭佳屿" +"466990","花蓮","Hualien","花蓮","화롄","花蓮","花蓮","花莲" +"467050","新屋","Xinwu","新屋","新屋","新屋","新屋","新屋" +"467080","宜蘭","Yilan","宜蘭","이란","宜蘭","宜蘭","宜兰" +"467110","金門","Kinmen","金門","진먼","金門","金門","金门" +"467270","田中","Tianzhong","田中","田中","田中","田中","田中" +"467280","後龍","Houlong","後龍","後龍","後龍","後龍","后龙" +"467290","古坑","Gukeng","古坑","古坑","古坑","古坑","古坑" +"467300","東吉島","Dongjidao","東吉島","東吉島","東吉島","東吉島","东吉岛" +"467350","澎湖","Penghu","澎湖","펑후","澎湖","澎湖","澎湖" +"467410","臺南","Tainan","台南","타이난","臺南","臺南","台南" +"467420","永康","Yongkang","永康","永康","永康","永康","永康" +"467441","高雄","Kaohsiung","高雄","가오슝","高雄","高雄","高雄" +"467480","嘉義","Chiayi","嘉義","자이","嘉義","嘉義","嘉义" +"467490","臺中","Taichung","台中","타이중","臺中","臺中","台中" +"467530","阿里山","Alishan","阿里山","阿里山","阿里山","阿里山","阿里山" +"467540","大武","Dawu","大武","大武","大武","大武","大武" +"467550","玉山","Yushan","玉山","玉山","玉山","玉山","玉山" +"467571","新竹","Hsinchu","新竹","신주","新竹","新竹","新竹" +"467590","恆春","Hengchun","恒春","恆春","恆春","恆春","恒春" +"467610","成功","Chenggong","成功","成功","成功","成功","成功" +"467620","蘭嶼","Lanyu","蘭嶼","蘭嶼","蘭嶼","蘭嶼","兰屿" +"467650","日月潭","Sun Moon Lake","日月潭","日月潭","日月潭","日月潭","日月潭" +"467660","臺東","Taitung","台東","타이둥","臺東","臺東","台东" +"467790","墾丁雷達站","Kenting","墾丁レーダー局","墾丁雷達站","墾丁雷達站","墾丁雷達站","垦丁雷达站" +"467990","馬祖","Matsu","馬祖","馬祖","馬祖","馬祖","马祖" +"12J990","口湖工作站","Kouhu Branch Station","口湖工作站","口湖工作站","口湖工作站","口湖工作站","口湖工作站" +"12Q970","東港工作站","Donggang Branch","東港工作站","東港工作站","東港工作站","東港工作站","东港工作站" +"12Q980","恆春工作站","Hengchun Branch","恆春工作站","恆春工作站","恆春工作站","恆春工作站","恒春工作站" +"42HA10","萬大發電廠","Wanta Hydro","萬大発電所","萬大發電廠","萬大發電廠","萬大發電廠","万大发电厂" +"72AI40","桃改樹林分場","Shulin Sub-station Of Taoyuan ARES","桃改樹林分場","桃改樹林分場","桃改樹林分場","桃改樹林分場","桃改树林分场" +"72C440","桃園農改場","桃園農改場","桃園農改場","桃園農改場","桃園農改場","桃園農改場","桃园农改场" +"72D080","桃改五峰分場","Wufeng Sub-station Of Taoyuan ARES","桃改五峰分場","桃改五峰分場","桃改五峰分場","桃改五峰分場","桃改五峰分场" +"72D680","桃改新埔分場","Sinpu Sub-station Of Taoyuan ARES","桃改新埔分場","桃改新埔分場","桃改新埔分場","桃改新埔分場","桃改新埔分场" +"72G600","臺中農改場","Ta Tsun","臺中農改場","臺中農改場","臺中農改場","臺中農改場","台中农改场" +"72HA00","中改埔里分場","Puli Sub-station Of Taichung ARES","中改埔里分場","中改埔里分場","中改埔里分場","中改埔里分場","中改埔里分场" +"72K220","南改斗南分場","Dounan Sub-station Of Tainan ARES","南改斗南分場","南改斗南分場","南改斗南分場","南改斗南分場","南改斗南分场" +"72M360","南改義竹分場","Yichu Sub-station Of Tainan ARES","南改義竹分場","南改義竹分場","南改義竹分場","南改義竹分場","南改义竹分场" +"72M700","南改鹿草分場","Lucao Sub-station Of Tainan ARES","南改鹿草分場","南改鹿草分場","南改鹿草分場","南改鹿草分場","南改鹿草分场" +"72N100","臺南農改場","Tainan","臺南農改場","臺南農改場","臺南農改場","臺南農改場","台南农改场" +"72N240","七股研究中心","Qigu Research Center","七股研究中心","七股研究中心","七股研究中心","七股研究中心","七股研究中心" +"72Q010","高雄農改場","Pingtung","高雄農改場","高雄農改場","高雄農改場","高雄農改場","高雄农改场" +"72S200","東改班鳩分場","Banjuou Sub-station Of Taitung ARES ","東改班鳩分場","東改班鳩分場","東改班鳩分場","東改班鳩分場","东改斑鸠分场" +"72S590","東改賓朗果園","Binlung Orchard Sub-station Of Taitung ARES ","東改賓朗果園","東改賓朗果園","東改賓朗果園","東改賓朗果園","东改宾朗果园" +"72T250","花蓮農改場","Gi An","花蓮農改場","花蓮農改場","花蓮農改場","花蓮農改場","花莲农改场" +"72U480","花改蘭陽分場","Lanyang Sub-station Of Hualien ARES","花改蘭陽分場","花改蘭陽分場","花改蘭陽分場","花改蘭陽分場","花改兰阳分场" +"72V140","高改旗南分場","Chinan Sub-station Of Kaohsiung ARES","高改旗南分場","高改旗南分場","高改旗南分場","高改旗南分場","高改旗南分场" +"82A750","茶改北部分場","North Branch Of TBRS","茶改北部分場","茶改北部分場","茶改北部分場","茶改北部分場","茶改北部分场" +"82C160","茶改場","Tea And Beverage Research Station","茶改場","茶改場","茶改場","茶改場","茶改场" +"82H320","茶改中部分場","Middle Branch Of TRES","茶改中部分場","茶改中部分場","茶改中部分場","茶改中部分場","茶改中部分场" +"82H840","茶改南部分場","South Branch Of TBRS","茶改南部分場","茶改南部分場","茶改南部分場","茶改南部分場","茶改南部分场" +"82S580","茶改東部分場","East Branch Of TBRS","茶改東部分場","茶改東部分場","茶改東部分場","茶改東部分場","茶改东部分场" +"A2C560","農工中心","農工中心","農工中心","農工中心","農工中心","農工中心","农工中心" +"A2K360","水試臺西試驗場","Taixi Experimental Fishing Ground","水試臺西実験場","水試臺西試驗場","水試臺西試驗場","水試臺西試驗場","水改台西试验场" +"A2K630","臺大雲林校區","Yunlin Branch Of NTU","台大雲林校区","臺大雲林校區","臺大雲林校區","臺大雲林校區","台大云林校区" +"A2N290","臺南蘭花園區","Taiwan Orchid","臺南蘭花園區","臺南蘭花園區","臺南蘭花園區","臺南蘭花園區","台南兰花园区" +"B2E890","畜試北區分所","North Branch Of TLRI","畜試北區分所","畜試北區分所","畜試北區分所","畜試北區分所","蓄试北区分所" +"B2N890","畜產試驗所","Hsin Hua","畜產実験所","畜產試驗所","畜產試驗所","畜產試驗所","畜产试验所" +"B2Q810","畜試南區分所","South Branch Of TLRI","畜試南區分所","畜試南區分所","畜試南區分所","畜試南區分所","蓄试南区分所" +"B2U990","畜試東區分所","East Branch Of TLRI","畜試東區分所","畜試東區分所","畜試東區分所","畜試東區分所","蓄试东区分所" +"C2A540","四堵","Sihdu","四堵","四堵","四堵","四堵","四堵" +"C2A560","福山","Fushan","福山","福山","福山","福山","福山" +"C2A650","火燒寮","Huoshaoliao","火燒寮","火燒寮","火燒寮","火燒寮","火烧寮" +"C2A660","瑞芳","Rueifang","瑞芳","瑞芳","瑞芳","瑞芳","瑞芳" +"C2A880","福隆","Fulong","福隆","福隆","福隆","福隆","福隆" +"C2A920","富貴角","Fugueijiao","富貴角","富貴角","富貴角","富貴角","富贵角" +"C2C410","中央大學","Ncu","中央大学","中央大學","中央大學","中央大學","中央大学" +"C2D720","關西工作站","Guanxi Experiment Station","関西工作站","關西工作站","關西工作站","關西工作站","关西工作站" +"C2D730","寶山農場","Baoshan Farm","宝山農場","寶山農場","寶山農場","寶山農場","宝山农场" +"C2D740","屯原","Tunyuan","屯原","屯原","屯原","屯原","屯原" +"C2E520","大湖","Dahu","大湖","大湖","大湖","大湖","大湖" +"C2E540","龍溪","Longxi","龍溪","龍溪","龍溪","龍溪","龙溪" +"C2E880","三義","Sanyi","三義","三義","三義","三義","三义" +"C2E970","八甲","Bajia","八甲","八甲","八甲","八甲","八甲" +"C2F000","大肚","Dadu","大肚","다두","大肚","大肚","大肚" +"C2F860","梨山","Lishan","梨山","梨山","梨山","梨山","梨山" +"C2F930","大甲","Dajia","大甲","다자","大甲","大甲","大甲" +"C2F990","摩天嶺","Motianling","摩天嶺","摩天嶺","摩天嶺","摩天嶺","摩天岭" +"C2F9A0","中竹林","Zhongzhulin","中竹林","中竹林","中竹林","中竹林","中竹林" +"C2FA00","烏石坑","Wushihkeng","烏石坑","烏石坑","烏石坑","烏石坑","乌石坑" +"C2FB50","出雲","Chuyun","出雲","出雲","出雲","出雲","出云" +"C2FB60","頭櫃山","Touguishan","頭櫃山","頭櫃山","頭櫃山","頭櫃山","头柜山" +"C2G640","鹿港","Lukang","鹿港","鹿港","鹿港","鹿港","鹿港" +"C2G840","北斗","Beidou","北斗","北斗","北斗","北斗","北斗" +"C2G870","芳苑","Fangyuan","芳苑","芳苑","芳苑","芳苑","芳苑" +"C2G980","田頭村","Toutian Village","田頭村","田頭村","田頭村","田頭村","田头村" +"C2G9A0","畜試所彰化","Changhua Branch Of TLRI","畜試所彰化","畜試所彰化","畜試所彰化","畜試所彰化","蓄试所彰化" +"C2H950","中寮","Zhongliao","中寮","中寮","中寮","中寮","中寮" +"C2H9D0","三隻寮","Sanziliao","三隻寮","三隻寮","三隻寮","三隻寮","三只寮" +"C2H9E0","國姓南港","Guoxing Nangang","国姓南港","國姓南港","國姓南港","國姓南港","国姓南港" +"C2H9F0","柑林","Ganlin","柑林","柑林","柑林","柑林","柑林" +"C2H9G0","百勝","Bosheng","百勝","百勝","百勝","百勝","百胜" +"C2H9H0","苗改南投蜂場","Nantou Bee Farm Of Miaoli TARI","苗改南投蜂場","苗改南投蜂場","苗改南投蜂場","苗改南投蜂場","苗改南投蜂场" +"C2H9J0","中台","Zhongtai","中台","中台","中台","中台","中台" +"C2H9L0","馬烈霸","Malieba","馬烈霸","馬烈霸","馬烈霸","馬烈霸","马烈霸" +"C2H9M0","發祥","Faxiang","發祥","發祥","發祥","發祥","发祥" +"C2H9N0","仁愛東眼","Renaidong","仁愛東眼","仁愛東眼","仁愛東眼","仁愛東眼","仁爱东眼" +"C2H9P0","伊拿谷","Yinagu","伊拿谷","伊拿谷","伊拿谷","伊拿谷","伊拿谷" +"C2H9Q0","北東眼山","Beidongyanshan","北東眼山","北東眼山","北東眼山","北東眼山","北东眼山" +"C2H9R0","卓社","Zhuoshe","卓社","卓社","卓社","卓社","卓社" +"C2H9S0","龍南","Longnan","龍南","龍南","龍南","龍南","龙南" +"C2H9T0","名間竹圍","Mingjianzhuwei","名間竹圍","名間竹圍","名間竹圍","名間竹圍","名间竹围" +"C2H9U0","鳳鵬","Fengpeng","鳳鵬","鳳鵬","鳳鵬","鳳鵬","凤鹏" +"C2H9W0","大坪頂農水","Dapingding Station","大坪頂農水","大坪頂農水","大坪頂農水","大坪頂農水","大坪顶农水" +"C2I090","鳳凰","Fenghuang","鳳凰","鳳凰","鳳凰","鳳凰","凤凰" +"C2K240","草嶺","Caoling","草嶺","草嶺","草嶺","草嶺","草岭" +"C2K610","草嶺石壁","Caolingshibi","草嶺石壁","草嶺石壁","草嶺石壁","草嶺石壁","草岭石壁" +"C2K620","馬光農場","Maguang Organic Agriculture Circular Park","馬光農場","馬光農場","馬光農場","馬光農場","马光农场" +"C2K630","荷苞","Hebao","荷苞","荷苞","荷苞","荷苞","荷苞" +"C2M410","馬頭山","Matoushan","馬頭山","馬頭山","馬頭山","馬頭山","马头山" +"C2M620","瑞里","Ruili","瑞里","瑞里","瑞里","瑞里","瑞里" +"C2M910","嘉義大學","Chiayi University","嘉義大学","嘉義大學","嘉義大學","嘉義大學","嘉义大学" +"C2M920","朴子農改","Pozi DARES","朴子農改","朴子農改","朴子農改","朴子農改","朴子农改" +"C2M930","石卓","Shizhuo","石卓","石卓","石卓","石卓","石卓" +"C2M940","日野賀","Riyehe","日野賀","日野賀","日野賀","日野賀","日野贺" +"C2M950","太和","Taihe","太和","太和","太和","太和","太和" +"C2M960","外寮","Wailiao","外寮","外寮","外寮","外寮","外寮" +"C2M970","碧湖","Bihu","碧湖","碧湖","碧湖","碧湖","碧湖" +"C2N160","西拉雅風管處","Siraya NSAH","西拉雅風管處","西拉雅風管處","西拉雅風管處","西拉雅風管處","西拉雅风管处" +"C2O810","曾文","Cengwen","曽文","曾文","曾文","曾文","曾文" +"C2O930","玉井","Yujing","玉井","玉井","玉井","玉井","玉井" +"C2O950","安南","Annan","安南","安南","安南","安南","安南" +"C2R170","屏東","Pingdong","屏東","핑둥","屏東","屏東","屏东" +"C2R970","屏科大","National Pingtung University","屏科大","屏科大","屏科大","屏科大","屏科大" +"C2V250","甲仙","Jiaxian","甲仙","甲仙","甲仙","甲仙","甲仙" +"C2V260","月眉","Yuemei","月眉","月眉","月眉","月眉","月眉" +"C2V310","美濃","Meinong","美濃","美濃","美濃","美濃","美浓" +"C2W030","金門農試所","Kimmann","金門農試所","金門農試所","金門農試所","金門農試所","金门农试所" +"C2W230","畜試所澎湖","Penghu Field Area Of TLRI","畜試所澎湖","畜試所澎湖","畜試所澎湖","畜試所澎湖","蓄试所澎湖" +"CAG100","王功漁港","Wanggong Fishing Port","王功漁港","王功漁港","王功漁港","王功漁港","王功渔港" +"CAH030","茶改場竹圍站","TRES Chuwei Station","茶改場竹圍站","茶改場竹圍站","茶改場竹圍站","茶改場竹圍站","茶改场竹围站" +"CAJ050","海口故事園區","Haikou Story Camping Park","海口故事園區","海口故事園區","海口故事園區","海口故事園區","海口故事园区" +"CAL110","布袋國中","Budai Junior High School","布袋國中","布袋國中","布袋國中","布袋國中","布袋国中" +"CAN130","水試所海水繁養殖中心","Mariculture Research Center","水試所海水繁養殖中心","水試所海水繁養殖中心","水試所海水繁養殖中心","水試所海水繁養殖中心","水试所海水繁养殖中心" +"CAN140","六官養殖協會","Liuguan Aquaculture","六官養殖協會","六官養殖協會","六官養殖協會","六官養殖協會","六官养殖协会" +"CAQ030","崎峰國小","Cifong Elementary School","崎峰國小","崎峰國小","崎峰國小","崎峰國小","崎峰国小" +"E2H360","蓮華池","Lienhuchih","蓮華池","蓮華池","蓮華池","蓮華池","莲华池" +"E2HA20","林試畢祿溪站","Pilushi","林試畢祿溪站","林試畢祿溪站","林試畢祿溪站","林試畢祿溪站","林试毕禄溪站" +"E2K600","四湖植物園","Sihu Botanical Garden","四湖植物園","四湖植物園","四湖植物園","四湖植物園","四湖植物园" +"E2P980","林試六龜中心","Lioukuei Research Center ","林試六龜中心","林試六龜中心","林試六龜中心","林試六龜中心","林试六龟中心" +"E2P990","林試扇平站","Shanping","林試扇平站","林試扇平站","林試扇平站","林試扇平站","林试扇平站" +"E2S960","林試太麻里2","Taimalee2","林試太麻里2","林試太麻里2","林試太麻里2","林試太麻里2","林试太麻里2" +"E2S980","林試太麻里1","Taimalee Research Center 1","林試太麻里1","林試太麻里1","林試太麻里1","林試太麻里1","林试太麻里1" +"G2AI50","關渡","Guandu","關渡","關渡","關渡","關渡","关渡" +"G2F820","農試所(霧峰)","Taichung","農試所(霧峰)","農試所(霧峰)","農試所(霧峰)","農試所(霧峰)","农试所(雾峰)" +"G2L020","農試嘉義分所","Chiayi Sub-station Of TARI","農試嘉義分所","農試嘉義分所","農試嘉義分所","農試嘉義分所","农试嘉义分所" +"G2M350","農試溪口農場","Xikou Farm Of TARI","農試溪口農場","農試溪口農場","農試溪口農場","農試溪口農場","农试溪口农场" +"G2P820","農試鳳山分所","Fengshan Tropical Horticultural Of TARI","農試鳳山分所","農試鳳山分所","農試鳳山分所","農試鳳山分所","农试凤山分所" +"K2E360","苗栗農改場","苗栗農改場","苗栗農改場","苗栗農改場","苗栗農改場","苗栗農改場","苗栗农改场" +"K2E710","苗改生物防治研究中心","Biological Control Branch Of Miaoli TARI","苗改生物防治研究中心","苗改生物防治研究中心","苗改生物防治研究中心","苗改生物防治研究中心","苗改生物防治研究中心" +"K2F750","種苗改良場","Shin She","種苗改良場","種苗改良場","種苗改良場","種苗改良場","种苗改良场" +"U2H480","溪頭","Hsi Tou","溪頭","溪頭","溪頭","溪頭","溪头" +"U2HA30","臺大和社","NTU Exfohoshe","臺大和社","臺大和社","臺大和社","臺大和社","台大和社" +"U2HA40","臺大內茅埔","NTU Exfoneimoupu","臺大內茅埔","臺大內茅埔","臺大內茅埔","臺大內茅埔","台大內茅埔" +"U2HA50","臺大竹山","NTU Experimental Forest","臺大竹山","臺大竹山","臺大竹山","臺大竹山","台大竹山" +"V2C250","八德合作社","Bade Cooperative","八德合作社","八德合作社","八德合作社","八德合作社","八德合作社" +"V2C260","八德蔬果","Bade Fruit And Vegetable","八德蔬果","八德蔬果","八德蔬果","八德蔬果","八德蔬果" +"V2K610","大庄合作社","Dazhuang Cooperative","大庄合作社","大庄合作社","大庄合作社","大庄合作社","大庄合作社" +"V2K620","麥寮合作社","Mailiao Cooperative","麥寮合作社","麥寮合作社","麥寮合作社","麥寮合作社","麦寮合作社" +"C0A520","山佳","Shanjia","山佳","山佳","山佳","山佳","山佳" +"C0A530","坪林","Pinglin","坪林","坪林","坪林","坪林","坪林" +"C0A550","泰平","Taiping","泰平","泰平","泰平","泰平","泰平" +"C0A570","桶後","Tonghou","桶後","桶後","桶後","桶後","桶后" +"C0A640","石碇","Shihding","石碇","石碇","石碇","石碇","石碇" +"C0A770","科教館","Science Education Center ","科教館","科教館","科教館","科教館","科教馆" +"C0A860","大坪","Daping","大坪","大坪","大坪","大坪","大坪" +"C0A870","五指山","Wujhihshan","五指山","五指山","五指山","五指山","五指山" +"C0A890","雙溪","Shuangsi","双渓","雙溪","雙溪","雙溪","双溪" +"C0A931","三和","Sanhe","三和","三和","三和","三和","三和" +"C0A940","金山","Jinshan","金山","金山","金山","金山","金山" +"C0A950","鼻頭角","Bitoujiao","鼻頭角","鼻頭角","鼻頭角","鼻頭角","鼻头角" +"C0A970","三貂角","Sandiaojiao","三貂角","三貂角","三貂角","三貂角","三貂角" +"C0A980","社子","Shezih","社子","社子","社子","社子","社子" +"C0A9C0","天母","Tianmu","天母","天母","天母","天母","天母" +"C0A9F0","內湖","Neihu","内湖","內湖","內湖","內湖","内湖" +"C0AC40","大屯山","Datunshan","大屯山","大屯山","大屯山","大屯山","大屯山" +"C0AC60","三峽","Sanshia","三峡","三峽","三峽","三峽","三峡" +"C0AC70","信義","Xinyi","信義","信義","信義","信義","信义" +"C0AC80","文山","Wenshan","文山","文山","文山","文山","文山" +"C0ACA0","新莊","Xinzhuang","新荘","新莊","新莊","新莊","新庄" +"C0AD10","八里","Bali","八里","八里","八里","八里","八里" +"C0AD30","蘆洲","Lujhou","蘆洲","蘆洲","蘆洲","蘆洲","芦洲" +"C0AD40","土城","Tucheng","土城","土城","土城","土城","土城" +"C0AD50","鶯歌","Yingge","鶯歌","鶯歌","鶯歌","鶯歌","莺歌" +"C0AG80","中和","Zhonghe","中和","中和","中和","中和","中和" +"C0AH00","汐止","Xizhi","汐止","汐止","汐止","汐止","汐止" +"C0AH10","永和","Yonghe","永和","永和","永和","永和","永和" +"C0AH30","五分山","Wufengshan","五分山","五分山","五分山","五分山","五分山" +"C0AH40","平等","Pingdeng","平等","平等","平等","平等","平等" +"C0AH50","林口","Linkou","林口","林口","林口","林口","林口" +"C0AH70","松山","Songshan","松山","松山","松山","松山","松山" +"C0AH80","深坑","Shenkeng","深坑","深坑","深坑","深坑","深坑" +"C0AH90","福山植物園","Fushan Botanical Garden","福山植物園","福山植物園","福山植物園","福山植物園","福山植物园" +"C0AI00","五股","Wugu","五股","五股","五股","五股","五股" +"C0AI10","屈尺","Quchi","屈尺","屈尺","屈尺","屈尺","屈尺" +"C0AI20","白沙灣","Baishawan","白沙灣","白沙灣","白沙灣","白沙灣","白沙湾" +"C0AI30","三重","Sanchong","三重","三重","三重","三重","三重" +"C0AI40","石牌","Shipai","石牌","石牌","石牌","石牌","石牌" +"C0AJ20","野柳","Yehliou","野柳","野柳","野柳","野柳","野柳" +"C0AJ30","淡水觀海","Danshuei Guanhai","淡水觀海","淡水觀海","淡水觀海","淡水觀海","淡水观海" +"C0AJ40","石門","Shimen","石門","石門","石門","石門","石门" +"C0AJ50","水湳洞","Shuinandong","水湳洞","水湳洞","水湳洞","水湳洞","水湳洞" +"C0AJ60","六塊厝","Lioukuaitsuo","六塊厝","六塊厝","六塊厝","六塊厝","六块厝" +"C0AJ70","田寮","Tianliao","田寮","田寮","田寮","田寮","田寮" +"C0AJ80","板橋","Banchiao","板橋","板橋","板橋","板橋","板桥" +"C0AJ90","澳底","Aodi","澳底","澳底","澳底","澳底","澳底" +"C0AK10","太平里","Taiping Vil.","太平里","太平里","太平里","太平里","太平里" +"C0AK30","硬漢嶺","Yinghanling","硬漢嶺","硬漢嶺","硬漢嶺","硬漢嶺","硬汉岭" +"C0B010","七堵","Qidu","七堵","七堵","七堵","七堵","七堵" +"C0B020","基隆嶼","Keelung Islet","基隆嶼","基隆嶼","基隆嶼","基隆嶼","基隆屿" +"C0B040","大武崙","Dawulun","大武崙","大武崙","大武崙","大武崙","大武仑 +" +"C0B050","八斗子","Badouzi","八斗子","八斗子","八斗子","八斗子","八斗子" +"C0B060","暖暖","Nuannuan","暖暖","暖暖","暖暖","暖暖","暖暖" +"C0C460","復興","Fuxing","復興","復興","復興","復興","复兴" +"C0C480","桃園","Taoyuan","桃園","타오위안","桃園","桃園","桃园" +"C0C490","八德","Bade","八徳","八德","八德","八德","八德" +"C0C590","觀音","Guanyin","観音","觀音","觀音","觀音","观音" +"C0C620","蘆竹","Luzhu","蘆竹","蘆竹","蘆竹","蘆竹","芦竹" +"C0C630","大溪","Dasi","大渓","大溪","大溪","大溪","大溪" +"C0C650","平鎮","Pingjhen","平鎮","平鎮","平鎮","平鎮","平镇" +"C0C660","楊梅","Yangmei","楊梅","楊梅","楊梅","楊梅","杨梅" +"C0C670","龍潭","Longtan","龍潭","龍潭","龍潭","龍潭","龙潭" +"C0C680","龜山","Guishan","亀山","龜山","龜山","龜山","龟山" +"C0C700","中壢","Zhongli","中壢","中壢","中壢","中壢","中坜" +"C0C710","大溪永福","Yongfu Daxi","大溪永福","大溪永福","大溪永福","大溪永福","大溪永福" +"C0C720","竹圍","Jhuwei","竹圍","竹圍","竹圍","竹圍","竹围" +"C0C730","中大臨海站","Jhongda Coastal Station","中大臨海站","中大臨海站","中大臨海站","中大臨海站","中大临海站" +"C0C740","觀音工業區","Guanyin Industrial Area","觀音工業區","觀音工業區","觀音工業區","觀音工業區","观音工业区" +"C0C750","新興坑尾","Sinsingkengwei","新興坑尾","新興坑尾","新興坑尾","新興坑尾","新兴坑尾" +"C0C790","東眼山","Dongyanshan","東眼山","東眼山","東眼山","東眼山","东眼山" +"C0C800","四稜","Sileng","四稜","四稜","四稜","四稜","四棱" +"C0D360","梅花","Meihua","梅花","梅花","梅花","梅花","梅花" +"C0D430","峨眉","Emei","峨眉","峨眉","峨眉","峨眉","峨眉" +"C0D480","打鐵坑","Datiekeng","打鐵坑","打鐵坑","打鐵坑","打鐵坑","打铁坑" +"C0D540","橫山","Hengshan","横山","橫山","橫山","橫山","横山" +"C0D550","雪霸","Xueba","雪霸","雪霸","雪霸","雪霸","雪霸" +"C0D560","竹東","Zhudong","竹東","竹東","竹東","竹東","竹东" +"C0D580","寶山","Baoshan","宝山","寶山","寶山","寶山","宝山" +"C0D590","新豐","Sinfong","新豊","新豐","新豐","新豐","新丰" +"C0D650","湖口","Hukou","湖口","湖口","湖口","湖口","湖口" +"C0D660","新竹市東區","Dongqu Hsinshu City","新竹市東區","新竹市東區","新竹市東區","新竹市東區","新竹市东区" +"C0D670","海天一線","Haitianyisian","海天一線","海天一線","海天一線","海天一線","海天一线" +"C0D680","香山濕地","Siangshan Wetland","香山濕地","香山濕地","香山濕地","香山濕地","香山湿地" +"C0D690","外湖","Waihu","外湖","外湖","外湖","外湖","外湖" +"C0D700","關西","Guanxi","関西","關西","關西","關西","关西" +"C0D750","樂山林道6k","Leshan 6k","樂山林道6k","樂山林道6k","樂山林道6k","樂山林道6k","乐林山道6K" +"C0D760","大坪苗圃","Daping Nurserygarden","大坪苗圃","大坪苗圃","大坪苗圃","大坪苗圃","大坪苗圃" +"C0E420","竹南","Jhunan","竹南","竹南","竹南","竹南","竹南" +"C0E430","南庄","Nanzhuang","南庄","南庄","南庄","南庄","南庄" +"C0E550","明德","Mingde","明德","明德","明德","明德","明德" +"C0E570","白沙屯","Baishatun","白沙屯","白沙屯","白沙屯","白沙屯","白沙屯" +"C0E590","通霄","Tongxiao","通霄","通霄","通霄","通霄","通宵" +"C0E610","馬都安","Madu-An","馬都安","馬都安","馬都安","馬都安","马都安" +"C0E730","頭份","Toufen","頭份","頭份","頭份","頭份","头份" +"C0E740","造橋","Zaoqiao","造橋","造橋","造橋","造橋","造桥" +"C0E750","苗栗","Miaoli","苗栗","먀오리","苗栗","苗栗","苗栗" +"C0E780","銅鑼","Tongluo","銅鑼","銅鑼","銅鑼","銅鑼","铜锣" +"C0E791","卓蘭","Zhuolan","卓蘭","卓蘭","卓蘭","卓蘭","卓兰" +"C0E810","西湖","Xihu","西湖","西湖","西湖","西湖","西湖" +"C0E820","獅潭","Shitan","獅潭","獅潭","獅潭","獅潭","狮潭" +"C0E830","苑裡","Yuanli","苑裡","苑裡","苑裡","苑裡","苑里" +"C0E850","大河","Dahe","大河","大河","大河","大河","大河" +"C0E870","高鐵苗栗","THSR Miaoli","高鐵苗栗","高鐵苗栗","高鐵苗栗","高鐵苗栗","高铁苗栗" +"C0E910","海埔","Haipu","海埔","海埔","海埔","海埔","海埔" +"C0E920","通霄漁港","Tongsiao Fishing Harbor","通霄漁港","通霄漁港","通霄漁港","通霄漁港","通宵渔港" +"C0E930","龍鳳","Longfong","龍鳳","龍鳳","龍鳳","龍鳳","龙凤" +"C0E940","雪見","Shiuejian","雪見","雪見","雪見","雪見","雪见" +"C0E950","松安","Songan","松安","松安","松安","松安","松安" +"C0E960","觀霧分站","Guanwu","觀霧分站","觀霧分站","觀霧分站","觀霧分站","观雾分站" +"C0F0A0","雪山圈谷","Xueshanjuangu","雪山圈谷","雪山圈谷","雪山圈谷","雪山圈谷","雪山圈谷" +"C0F0B0","石岡","Shigang","石岡","스강","石岡","石岡","石冈" +"C0F0C0","中坑","Zhongkeng","中坑","中坑","中坑","中坑","中坑" +"C0F0D0","審馬陣","Shenmazhen","審馬陣","審馬陣","審馬陣","審馬陣","审马阵" +"C0F0E0","南湖圈谷","Nanhuquangu","南湖圈谷","南湖圈谷","南湖圈谷","南湖圈谷","南胡圈谷" +"C0F850","東勢","Dongshi","東勢","둥스","東勢","東勢","东势" +"C0F970","大坑","Dakeng","大坑","大坑","大坑","大坑","大坑" +"C0F9I0","神岡","Shengang","神岡","룽징","神岡","神岡","神冈" +"C0F9K0","大安","Da-An","大安","다안","大安","大安","大安" +"C0F9L0","后里","Houli","后里","허우리","后里","后里","后里" +"C0F9M0","豐原","Fengyuan","豊原","펑위안","豐原","豐原","丰原" +"C0F9N0","大里","Dali","大里","다리","大里","大里","大里" +"C0F9O0","潭子","Tanzi","潭子","탄쯔","潭子","潭子","潭子" +"C0F9P0","清水","Qingshui","清水","清水","清水","清水","清水" +"C0F9Q0","外埔","Waipu","外埔","와이푸","外埔","外埔","外埔" +"C0F9R0","龍井","Longjing","龍井","룽징","龍井","龍井","龙井" +"C0F9S0","烏日","Wuri","烏日","우르","烏日","烏日","乌日" +"C0F9T0","西屯","Xitun","西屯","시툰","西屯","西屯","西屯" +"C0F9U0","南屯","Nantun","南屯","난툰","南屯","南屯","南屯" +"C0F9V0","新社","Xinshe","新社","신서","新社","新社","新社" +"C0F9X0","大雅(中科園區)","Daya","大雅(中科園區)","大雅(中科園區)","大雅(中科園區)","大雅(中科園區)","大雅(中科园区)" +"C0F9Y0","桃山","Taoshan","桃山","桃山","桃山","桃山","桃山" +"C0F9Z0","雪山東峰","Xueshandongfeng","雪山東峰","雪山東峰","雪山東峰","雪山東峰","雪山东峰" +"C0FA10","松柏","Songbai","松柏","松柏","松柏","松柏","松柏" +"C0FA20","溫寮","Wunliao","溫寮","溫寮","溫寮","溫寮","温寮" +"C0FA30","梧棲","Wuqi","梧棲","우치","梧棲","梧棲","梧栖" +"C0FA40","臺中電廠","Taichung?Power Plant","臺中電廠","臺中電廠","臺中電廠","臺中電廠","台中电厂" +"C0FA50","霧峰","Wufeng","霧峰","우펑","霧峰","霧峰","雾峰" +"C0FA60","鞍馬山工作站","Anmashan Office","鞍馬山工作站","鞍馬山工作站","鞍馬山工作站","鞍馬山工作站","鞍马山工作站" +"C0FA70","大雪山埡口","Dashiueshan Yakou","大雪山埡口","大雪山埡口","大雪山埡口","大雪山埡口","大雪山哑口" +"C0FA80","小雪山天池","Shiaushiueshan Tianchr","小雪山天池","小雪山天池","小雪山天池","小雪山天池","小雪山天池" +"C0FA90","小雪山林道","Shiaushiueshan","小雪山林道","小雪山林道","小雪山林道","小雪山林道","小雪山林道" +"C0FB00","大雪山","Dashiueshan","大雪山","大雪山","大雪山","大雪山","大雪山" +"C0FB10","出雲山苗圃","Chuyunshan","出雲山苗圃","出雲山苗圃","出雲山苗圃","出雲山苗圃","出云山苗圃" +"C0FB20","雪山橋","Shiueshanchiau","雪山橋","雪山橋","雪山橋","雪山橋","雪山桥" +"C0FB30","八仙山苗圃","Bashianshan","八仙山苗圃","八仙山苗圃","八仙山苗圃","八仙山苗圃","八仙山苗圃" +"C0FB40","中橫21.6k","Chungheng 21.6k","中橫21.6k","中橫21.6k","中橫21.6k","中橫21.6k","中橫21.6K" +"C0FB70","大甲溪埔","Dajia, Xipu","大甲溪埔","大甲溪埔","大甲溪埔","大甲溪埔","大甲溪埔" +"C0G620","芬園","Fenyuan","芬園","芬園","芬園","芬園","芬园" +"C0G650","員林","Yuanlin","員林","員林","員林","員林","员林" +"C0G660","溪湖","Xihu","渓湖","溪湖","溪湖","溪湖","溪湖" +"C0G720","溪州","Xizhou","渓州","溪州","溪州","溪州","溪洲" +"C0G730","二林","Erlin","二林","二林","二林","二林","二林" +"C0G740","大城","Dacheng","大城","大城","大城","大城","大城" +"C0G770","福興","Fuxing","福興","福興","福興","福興","福兴" +"C0G780","秀水","Xiushui","秀水","秀水","秀水","秀水","秀水" +"C0G800","埔鹽","Puyan","埔塩","埔鹽","埔鹽","埔鹽","埔盐" +"C0G810","埔心","Puxin","埔心","埔心","埔心","埔心","埔心" +"C0G820","田尾","Tianwei","田尾","田尾","田尾","田尾","田尾" +"C0G830","埤頭","Pitou","埤頭","埤頭","埤頭","埤頭","埤头" +"C0G860","社頭","Shetou","社頭","社頭","社頭","社頭","社头" +"C0G880","二水","Ershui","二水","二水","二水","二水","二水" +"C0G890","伸港","Shenggang","伸港","伸港","伸港","伸港","伸港" +"C0G900","線西","Xianxi","線西","線西","線西","線西","线西" +"C0G910","花壇","Huatan","花壇","花壇","花壇","花壇","花坛" +"C0G920","永靖","Yongjing ","永靖","永靖","永靖","永靖","永靖" +"C0G940","竹塘","Zhutang","竹塘","竹塘","竹塘","竹塘","竹塘" +"C0G950","防潮門","Fangchaomen","防潮門","防潮門","防潮門","防潮門","防潮门" +"C0G960","福寶","Fubao","福寶","福寶","福寶","福寶","福宝" +"C0G970","三豐","Sanfong","三豐","三豐","三豐","三豐","三丰" +"C0G9B0","和美","Hemei","和美","和美","和美","和美","和美" +"C0H890","埔里","Puli","埔里","埔里","埔里","埔里","埔里" +"C0H960","草屯","Caotun","草屯","草屯","草屯","草屯","草屯" +"C0H990","昆陽","Kunyang","昆陽","昆陽","昆陽","昆陽","昆阳" +"C0H9A0","神木村","Shenmu Village","神木村","神木村","神木村","神木村","神木村" +"C0H9C0","合歡山","Hehuan Mountain","合歡山","合歡山","合歡山","合歡山","合欢山" +"C0I010","廬山","Lushan","廬山","廬山","廬山","廬山","庐山" +"C0I080","信義","Xinyi","信義","信義","信義","信義","信义" +"C0I110","竹山","Zhushan","竹山","竹山","竹山","竹山","竹山" +"C0I360","水里","Shuili","水里","水里","水里","水里","水里" +"C0I370","魚池","Yuchi","魚池","魚池","魚池","魚池","鱼池" +"C0I380","集集","Jiji","集集","集集","集集","集集","集集" +"C0I390","仁愛","Ren'Ai","仁愛","仁愛","仁愛","仁愛","仁爱" +"C0I410","名間","Mingjian","名間","名間","名間","名間","名间" +"C0I420","國姓","Guoxing","国姓","國姓","國姓","國姓","国姓" +"C0I460","南投","Nantou","南投","난터우","南投","南投","南投" +"C0I480","梅峰","Meifeng","梅峰","梅峰","梅峰","梅峰","梅峰" +"C0I490","萬大林道","Wandalindao","萬大林道","萬大林道","萬大林道","萬大林道","万大林道" +"C0I520","玉山風口","Yushanfengkou","玉山風口","玉山風口","玉山風口","玉山風口","玉山风口" +"C0I530","小奇萊","Xiaoqilai","小奇萊","小奇萊","小奇萊","小奇萊","小奇莱" +"C0I540","奇萊稜線","Qilailengxian","奇萊稜線","奇萊稜線","奇萊稜線","奇萊稜線","奇莱棱线" +"C0K250","崙背","Lunbei","崙背","崙背","崙背","崙背","仑背" +"C0K280","四湖","Sihu","四湖","四湖","四湖","四湖","四湖" +"C0K291","宜梧","Yiwu","宜梧","宜梧","宜梧","宜梧","宜梧" +"C0K330","虎尾","Huwei","虎尾","虎尾","虎尾","虎尾","虎尾" +"C0K390","土庫","Tuku","土庫","土庫","土庫","土庫","土库" +"C0K400","斗六","Douliu","斗六","斗六","斗六","斗六","斗六" +"C0K410","北港","Beigang","北港","北港","北港","北港","北港" +"C0K420","西螺","Xiluo","西螺","西螺","西螺","西螺","西螺" +"C0K430","褒忠","Baozhong","褒忠","褒忠","褒忠","褒忠","褒忠" +"C0K440","二崙","Erlun","二崙","二崙","二崙","二崙","二仑" +"C0K450","大埤","Dapi","大埤","大埤","大埤","大埤","大埤" +"C0K460","斗南","Dounan","斗南","斗南","斗南","斗南","鬥南" +"C0K470","林內","Linnei","林内","林內","林內","林內","林內" +"C0K480","莿桐","Citong","莿桐","莿桐","莿桐","莿桐","莿桐" +"C0K500","元長","Yuanchang","元長","元長","元長","元長","元长" +"C0K510","水林","Shuilin","水林","水林","水林","水林","水林" +"C0K530","臺西","Taixi","台西","臺西","臺西","臺西","台西" +"C0K550","蔦松","Niaosong","蔦松","蔦松","蔦松","蔦松","茑松" +"C0K560","棋山","Qishan","棋山","棋山","棋山","棋山","棋山" +"C0K580","高鐵雲林","THSR Yunlin","高鐵雲林","高鐵雲林","高鐵雲林","高鐵雲林","高铁云林" +"C0K590","雲林東勢","Dongshi, Yunlin County","雲林東勢","雲林東勢","雲林東勢","雲林東勢","云林东势" +"C0K600","箔子寮","Bozihliao","箔子寮","箔子寮","箔子寮","箔子寮","箔子寮" +"C0M520","東後寮","Donghouliao","東後寮","東後寮","東後寮","東後寮","东后寮" +"C0M530","奮起湖","Fenqihu","奮起湖","奮起湖","奮起湖","奮起湖","奋起湖" +"C0M640","中埔","Zhongpu","中埔","中埔","中埔","中埔","中埔" +"C0M650","朴子","Puzi","朴子","朴子","朴子","朴子","朴子" +"C0M660","溪口","Xikou","渓口","溪口","溪口","溪口","溪口" +"C0M670","大林","Dalin","大林","大林","大林","大林","大林" +"C0M680","太保","Taibao","太保","太保","太保","太保","太保" +"C0M690","水上","Shuishang","水上","水上","水上","水上","水上" +"C0M700","竹崎","Zhuqi","竹崎","竹崎","竹崎","竹崎","竹崎" +"C0M710","東石","Dongshi","東石","東石","東石","東石","东石" +"C0M720","番路","Fanlu","番路","番路","番路","番路","番路" +"C0M730","嘉義市東區","Dongqu Chiayi City","嘉義市東區","嘉義市東區","嘉義市東區","嘉義市東區","嘉义市东区" +"C0M740","六腳","Liujiao","六脚","六腳","六腳","六腳","六脚" +"C0M750","布袋","Budai","布袋","布袋","布袋","布袋","布袋" +"C0M760","民雄","Minxiong","民雄","民雄","民雄","民雄","民雄" +"C0M770","嘉義梅山","Meishan Chiayi County","嘉義梅山","嘉義梅山","嘉義梅山","嘉義梅山","嘉义梅山" +"C0M780","鹿草","Lucao","鹿草","鹿草","鹿草","鹿草","鹿草" +"C0M790","新港","Xingang","新港","新港","新港","新港","新港" +"C0M800","茶山","Chashan","茶山","茶山","茶山","茶山","茶山" +"C0M810","里佳","Lijia","里佳","里佳","里佳","里佳","里佳" +"C0M820","達邦","Dabang","達邦","達邦","達邦","達邦","达邦" +"C0M850","表湖","Biaohu","表湖","表湖","表湖","表湖","表湖" +"C0M860","新美","Shinmei","新美","新美","新美","新美","新美" +"C0M880","好美里","Haomeili","好美里","好美里","好美里","好美里","好美里" +"C0N010","鯤鯓國小","Kunshen Elementary School","鯤鯓國小","鯤鯓國小","鯤鯓國小","鯤鯓國小","鲲鯓国小" +"C0N020","城西","Chengsi","城西","城西","城西","城西","城西" +"C0N030","四草","Sihtsao","四草","四草","四草","四草","四草" +"C0N040","蘆竹溝","Lujhugou","蘆竹溝","蘆竹溝","蘆竹溝","蘆竹溝","芦竹沟" +"C0N050","蚵寮","Eliao","蚵寮","蚵寮","蚵寮","蚵寮","蚵寮" +"C0O830","北寮","Beiliao","北寮","北寮","北寮","北寮","北寮" +"C0O840","王爺宮","Wangyegong","王爺宮","王爺宮","王爺宮","王爺宮","王爷宫" +"C0O860","大內","Danei","大内","大內","大內","大內","大内" +"C0O900","善化","Shanhua","善化","善化","善化","善化","善化" +"C0O960","崎頂","Qiding","崎頂","崎頂","崎頂","崎頂","崎顶" +"C0O970","虎頭埤","Hutoupi","虎頭埤","虎頭埤","虎頭埤","虎頭埤","虎头埤" +"C0O980","新市","Xinshi","新市","新市","新市","新市","新市" +"C0O990","媽廟","Mamiao","媽廟","媽廟","媽廟","媽廟","妈庙" +"C0R100","尾寮山","Weiliaoshan","尾寮山","尾寮山","尾寮山","尾寮山","尾寮山" +"C0R130","阿禮","Ali","阿禮","阿禮","阿禮","阿禮","阿礼" +"C0R140","瑪家","Majia","瑪家","瑪家","瑪家","瑪家","玛家" +"C0R150","三地門","Sandimen","三地門","三地門","三地門","三地門","三地门" +"C0R160","鹽埔","Yanpuxinwei","塩埔","鹽埔","鹽埔","鹽埔","盐埔" +"C0R190","赤山","Chishan","赤山","赤山","赤山","赤山","赤山" +"C0R220","潮州","Chaojhou","潮州","潮州","潮州","潮州","潮州" +"C0R240","來義","Laiyi","来義","來義","來義","來義","来义" +"C0R260","春日","Chunri","春日","春日","春日","春日","春日" +"C0R270","琉球嶼","Liouciouyu","琉球嶼","琉球嶼","琉球嶼","琉球嶼","琉球屿" +"C0R280","檳榔","Binlang","檳榔","檳榔","檳榔","檳榔","槟榔" +"C0R320","車城","Checheng","車城","車城","車城","車城","车城" +"C0R341","牡丹","Mudan","牡丹","牡丹","牡丹","牡丹","牡丹" +"C0R350","貓鼻頭","Maobitou","貓鼻頭","貓鼻頭","貓鼻頭","貓鼻頭","猫鼻头" +"C0R440","大漢山","Dahanshan","大漢山","大漢山","大漢山","大漢山","大汉山" +"C0R470","高樹","Gaoshu","高樹","高樹","高樹","高樹","高树" +"C0R480","長治","Changzhi","長治","長治","長治","長治","长治" +"C0R490","九如","Jiuru","九如","九如","九如","九如","九如" +"C0R520","崁頂","Kanding","崁頂","崁頂","崁頂","崁頂","崁顶" +"C0R540","佳冬","Jiadong","佳冬","佳冬","佳冬","佳冬","佳冬" +"C0R550","新埤","Xinpi","新埤","新埤","新埤","新埤","新埤" +"C0R560","新園","Xinyuan","新園","新園","新園","新園","新园" +"C0R570","麟洛","Linluo","麟洛","麟洛","麟洛","麟洛","麟洛" +"C0R580","南州","Nanzhou","南州","南州","南州","南州","南州" +"C0R590","里港","Ligang","里港","里港","里港","里港","里港" +"C0R600","舊泰武","Jiutaiwu","舊泰武","舊泰武","舊泰武","舊泰武","旧泰武" +"C0R620","墾雷","Kenlei","墾雷","墾雷","墾雷","墾雷","垦雷" +"C0R640","東港","Donggang","東港","東港","東港","東港","东港" +"C0R650","竹田","Zhutian","竹田","竹田","竹田","竹田","竹田" +"C0R660","枋寮","Fangliao","枋寮","枋寮","枋寮","枋寮","枋寮" +"C0R670","楓港","Fenggang","楓港","楓港","楓港","楓港","枫港" +"C0R680","佳樂水","Jialeshui","佳樂水","佳樂水","佳樂水","佳樂水","佳乐水" +"C0R690","墾丁","Kenting","墾丁","墾丁","墾丁","墾丁","垦丁" +"C0R700","枋山","Fangshan","枋山","枋山","枋山","枋山","枋山" +"C0R710","龍磐","Longpan","龍磐","龍磐","龍磐","龍磐","龙磐" +"C0R720","旭海","Xuhai","旭海","旭海","旭海","旭海","旭海" +"C0R730","大坪頂","Dapingding","大坪頂","大坪頂","大坪頂","大坪頂","大坪顶" +"C0R741","獅子","Shizi","獅子","獅子","獅子","獅子","狮子" +"C0R750","四林格山","Silingeshan","四林格山","四林格山","四林格山","四林格山","四林格山" +"C0R760","南仁湖","Nanrenhu","南仁湖","南仁湖","南仁湖","南仁湖","南仁湖" +"C0R770","保力","Baoli","保力","保力","保力","保力","保力" +"C0R780","滿州","Manzhou","満州","滿州","滿州","滿州","满州" +"C0R790","九棚","Jiupeng","九棚","九棚","九棚","九棚","九棚" +"C0R800","丹路","Danlu","丹路","丹路","丹路","丹路","丹路" +"C0R810","內獅","Neishi","內獅","內獅","內獅","內獅","内狮" +"C0R820","白鷺","Bailu","白鷺","白鷺","白鷺","白鷺","白鹭" +"C0R830","高士","Gaoshi","高士","高士","高士","高士","高士" +"C0R840","牡丹池山","Mudanchisahn","牡丹池山","牡丹池山","牡丹池山","牡丹池山","牡丹池山" +"C0R850","林邊","Linbian","林辺","林邊","林邊","林邊","林边" +"C0R860","鼻頭","Bitou","鼻頭","鼻頭","鼻頭","鼻頭","鼻头" +"C0R870","興海","Singhai","興海","興海","興海","興海","兴海" +"C0R880","後壁湖","Houbihu","後壁湖","後壁湖","後壁湖","後壁湖","后壁湖" +"C0R890","山海","Shanhai","山海","山海","山海","山海","山海" +"C0R900","竹坑","Jhukeng","竹坑","竹坑","竹坑","竹坑","竹坑" +"C0R910","下寮","Sialiao","下寮","下寮","下寮","下寮","下寮" +"C0R920","塭仔","Wunzai","塭仔","塭仔","塭仔","塭仔","塭仔" +"C0R930","萬丹","Wandan","万丹","萬丹","萬丹","萬丹","万丹" +"C0R940","加祿堂","Jialutang","加祿堂","加祿堂","加祿堂","加祿堂","加禄堂" +"C0R950","萬隆國小","Wanlongguoxiao","萬隆國小","萬隆國小","萬隆國小","萬隆國小","万隆国小" +"C0R960","內埔","Neipu","内埔","內埔","內埔","內埔","内埔" +"C0S660","下馬","Xiama","下馬","下馬","下馬","下馬","下马" +"C0S690","太麻里","Taimali","太麻里","太麻里","太麻里","太麻里","太麻里" +"C0S700","知本","Jhihben","知本","知本","知本","知本","知本" +"C0S710","鹿野","Luye","鹿野","鹿野","鹿野","鹿野","鹿野" +"C0S730","綠島","Ludao","緑島","綠島","綠島","綠島","绿岛" +"C0S740","池上","Chihshang","池上","池上","池上","池上","池上" +"C0S750","向陽","Siangyang","向陽","向陽","向陽","向陽","向阳" +"C0S760","紅石","Hongshih","紅石","紅石","紅石","紅石","红石" +"C0S770","大溪山","Dasishan","大溪山","大溪山","大溪山","大溪山","大溪山" +"C0S790","金崙","Jinlun","金崙","金崙","金崙","金崙","金仑" +"C0S810","東河","Donghe","東河","東河","東河","東河","东河" +"C0S830","長濱","Changbin","長浜","長濱","長濱","長濱","长滨" +"C0S840","南田","Nantian","南田","南田","南田","南田","南田" +"C0S890","關山","Guanshan","関山","關山","關山","關山","关山" +"C0S900","蘭嶼高中","Lanyu High School","蘭嶼高中","蘭嶼高中","蘭嶼高中","蘭嶼高中","兰屿高中" +"C0S910","蘭嶼燈塔","Lanyu Lighthouse","蘭嶼燈塔","蘭嶼燈塔","蘭嶼燈塔","蘭嶼燈塔","兰屿灯塔" +"C0S920","金峰嘉蘭","Jialan Jinfeng","金峰嘉蘭","金峰嘉蘭","金峰嘉蘭","金峰嘉蘭","金峰嘉兰" +"C0S930","延平","Yanping","延平","延平","延平","延平","延平" +"C0S940","石寧山","Shiningshan","石寧山","石寧山","石寧山","石寧山","石宁山" +"C0S950","七塊厝","Qikuaicuo","七塊厝","七塊厝","七塊厝","七塊厝","七块厝" +"C0S960","香蘭","Xianglan","香蘭","香蘭","香蘭","香蘭","香兰" +"C0S970","加津林","Jiajinlin","加津林","加津林","加津林","加津林","加津林" +"C0S980","勝林山","Shenglinshan","勝林山","勝林山","勝林山","勝林山","胜林山" +"C0S990","山豬窟","Shanzhuku","山豬窟","山豬窟","山豬窟","山豬窟","山猪窟" +"C0SA00","歷坵","Liqiu","歷坵","歷坵","歷坵","歷坵","历坵" +"C0SA10","檳榔四格山","Binlangsigeshan","檳榔四格山","檳榔四格山","檳榔四格山","檳榔四格山","槟榔四格山" +"C0SA20","金崙山","Jinlunshan","金崙山","金崙山","金崙山","金崙山","金仑山" +"C0SA30","都歷","Duli","都歷","都歷","都歷","都歷","都历" +"C0SA40","瑞和","Ruihe","瑞和","瑞和","瑞和","瑞和","瑞和" +"C0SA60","知本(水試所)","Zhiben (FRI)","知本(水試所)","知本(水試所)","知本(水試所)","知本(水試所)","知本(水试所)" +"C0SA80","土坂","Tuban","土坂","土坂","土坂","土坂","土坂" +"C0SA90","達仁林場","Darenlinchang","達仁林場","達仁林場","達仁林場","達仁林場","达仁林场" +"C0SB10","美和","Meihe","美和","美和","美和","美和","美和" +"C0SB20","富岡","Fugang","富岡","富岡","富岡","富岡","富冈" +"C0SB30","新蘭","Dulan Fire Brigade","新蘭","新蘭","新蘭","新蘭","新兰" +"C0SB40","興隆"," Xinglong","興隆","興隆","興隆","興隆","兴隆" +"C0SB50","叭嗡嗡","Baweng","叭嗡嗡","叭嗡嗡","叭嗡嗡","叭嗡嗡","叭嗡嗡" +"C0SB60","白守蓮","Baishoulian","白守蓮","白守蓮","白守蓮","白守蓮","白守莲" +"C0SB70","小港漁港","Xiaogang Fishing Harbor","小港漁港","小港漁港","小港漁港","小港漁港","小港渔港" +"C0SB80","長濱漁港","Changbin Fishing Harbor","長濱漁港","長濱漁港","長濱漁港","長濱漁港","长滨渔港" +"C0T790","大禹嶺","Dayuling","大禹嶺","大禹嶺","大禹嶺","大禹嶺","大禹岭" +"C0T820","天祥","Tianxiang","天祥","天祥","天祥","天祥","天祥" +"C0T870","鯉魚潭","Liyutan","鯉魚潭","鯉魚潭","鯉魚潭","鯉魚潭","鲤鱼潭" +"C0T900","西林","Xilin","西林","西林","西林","西林","西林" +"C0T960","光復","Guangfu","光復","光復","光復","光復","光复" +"C0T9A0","月眉山","Yuemeishan","月眉山","月眉山","月眉山","月眉山","月眉山" +"C0T9B0","水源","Shuiyuan","水源","水源","水源","水源","水源" +"C0T9D0","和中","Hezhong","和中","和中","和中","和中","和中" +"C0T9E0","大坑","Dakeng","大坑","大坑","大坑","大坑","大坑" +"C0T9F0","水璉","Shuilian","水璉","水璉","水璉","水璉","水琏" +"C0T9G0","鳳林山","Fenglinshan","鳳林山","鳳林山","鳳林山","鳳林山","凤林山" +"C0T9H0","加路蘭山","Jialulanshan","加路蘭山","加路蘭山","加路蘭山","加路蘭山","加路兰山" +"C0T9I0","豐濱","Fengbin","豊浜","豐濱","豐濱","豐濱","丰滨" +"C0T9M0","靜浦","Jingpu","靜浦","靜浦","靜浦","靜浦","静埔" +"C0T9N0","富里","Fuli","富里","富里","富里","富里","富里" +"C0TA10","花蓮漁港","Hualien Fishing Harbor","花蓮漁港","花蓮漁港","花蓮漁港","花蓮漁港","花莲渔港" +"C0TA20","加灣","Jiawan","加灣","加灣","加灣","加灣","加湾" +"C0TA30","鹽寮","Yanliao","鹽寮","鹽寮","鹽寮","鹽寮","盐寮" +"C0TA40","秀林","Xiulin","秀林","秀林","秀林","秀林","秀林" +"C0TA50","和仁","Heren","和仁","和仁","和仁","和仁","和仁" +"C0TA80","立霧山","Liwushan","立霧山","立霧山","立霧山","立霧山","立雾山" +"C0U520","雙連埤","Shuanglianpi","雙連埤","雙連埤","雙連埤","雙連埤","双连埤" +"C0U600","礁溪","Chiaoshi","礁渓","礁溪","礁溪","礁溪","礁溪" +"C0U650","玉蘭","Yulan","玉蘭","玉蘭","玉蘭","玉蘭","玉兰" +"C0U710","太平山","Taipingshan","太平山","太平山","太平山","太平山","太平山" +"C0U720","南山","Nanshan","南山","南山","南山","南山","南山" +"C0U750","龜山島","Gueishandao","龜山島","龜山島","龜山島","龜山島","龟山岛" +"C0U760","東澳","Dong-Ao","東澳","東澳","東澳","東澳","东澳" +"C0U770","南澳","Nanao","南澳","南澳","南澳","南澳","南澳" +"C0U780","五結","Wujie","五結","五結","五結","五結","五结" +"C0U860","頭城","Toucheng","頭城","頭城","頭城","頭城","头城" +"C0U870","大礁溪","Dajiaoxi","大礁溪","大礁溪","大礁溪","大礁溪","大礁溪" +"C0U880","北關","Beiguan","北關","北關","北關","北關","北关" +"C0U890","三星","Sanxing","三星","三星","三星","三星","三星" +"C0U900","內城","Neicheng","內城","內城","內城","內城","内城" +"C0U910","冬山","Dongshan","冬山","冬山","冬山","冬山","冬山" +"C0U940","羅東","Luodong","羅東","羅東","羅東","羅東","罗东" +"C0U950","鶯子嶺","Yingziling","鶯子嶺","鶯子嶺","鶯子嶺","鶯子嶺","莺子岭" +"C0U960","翠峰湖","Cuifenghu","翠峰湖","翠峰湖","翠峰湖","翠峰湖","翠峰湖" +"C0U970","大福","Dafu","大福","大福","大福","大福","大福" +"C0U980","坪林石牌","Shipai Pinglin","坪林石牌","坪林石牌","坪林石牌","坪林石牌","坪林石牌" +"C0U990","員山","Yuanshan","員山","員山","員山","員山","员山" +"C0UA00","土場","Tuchang","土場","土場","土場","土場","土场" +"C0UA10","鴛鴦湖","Yuanyanghu","鴛鴦湖","鴛鴦湖","鴛鴦湖","鴛鴦湖","鸳鸯湖" +"C0UA20","多加屯","Duojiatun","多加屯","多加屯","多加屯","多加屯","多加屯" +"C0UA30","白嶺","Bailing","白嶺","白嶺","白嶺","白嶺","白岭" +"C0UA40","西德山","Xideshan","西德山","西德山","西德山","西德山","西德山" +"C0UA50","西帽山","Ximaoshan","西帽山","西帽山","西帽山","西帽山","西帽山" +"C0UA60","樟樹山","Zhangshushan","樟樹山","樟樹山","樟樹山","樟樹山","樟树山" +"C0UA70","桃源谷","Taoyuangu","桃源谷","桃源谷","桃源谷","桃源谷","桃源谷" +"C0UA80","大溪漁港","Dasi Fishing Harbor","大溪漁港","大溪漁港","大溪漁港","大溪漁港","大溪渔港" +"C0UA90","石城","Shihcheng","石城","石城","石城","石城","石城" +"C0UB00","淡江大學蘭陽校園","Tamkang Lanyang Campus","淡江大学蘭陽キャンパス","淡江大學蘭陽校園","淡江大學蘭陽校園","淡江大學蘭陽校園","淡江大学兰阳校园" +"C0UB10","蘇澳","Suao","蘇澳","蘇澳","蘇澳","蘇澳","苏澳" +"C0UB20","壯圍","Jhuangwei","壮囲","壯圍","壯圍","壯圍","壮围" +"C0UB60","明池","Mingchr","明池","明池","明池","明池","明池" +"C0UB70","太平山中間站","Jhongjian","太平山中間站","太平山中間站","太平山中間站","太平山中間站","太平山中间站" +"C0UB80","翠峰林道6K","Trifong 6k","翠峰林道6K","翠峰林道6K","翠峰林道6K","翠峰林道6K","翠峰林道6K" +"C0UB90","太平山莊","Taipingshan Villa","太平山莊","太平山莊","太平山莊","太平山莊","太平山庄" +"C0V210","復興","Fuxing","復興","復興","復興","復興","复兴" +"C0V350","溪埔","Xipu","溪埔","溪埔","溪埔","溪埔","溪埔" +"C0V360","內門","Neimen","内門","內門","內門","內門","内门" +"C0V370","古亭坑","Gutingkeng","古亭坑","古亭坑","古亭坑","古亭坑","古亭坑" +"C0V400","阿公店","Agongdian","阿公店","阿公店","阿公店","阿公店","阿公店" +"C0V440","鳳山","Fengshan","鳳山","鳳山","鳳山","鳳山","凤山" +"C0V450","鳳森","Fengsen","鳳森","鳳森","鳳森","鳳森","凤森" +"C0V490","新興","Sinsing","新興","新興","新興","新興","新兴" +"C0V530","阿蓮","Alian","阿蓮","阿蓮","阿蓮","阿蓮","阿连" +"C0V610","梓官","Ziguan","梓官","梓官","梓官","梓官","梓官" +"C0V620","永安","Yong'An","永安","永安","永安","永安","永安" +"C0V630","茄萣","Qieding","茄萣","茄萣","茄萣","茄萣","茄萣" +"C0V640","湖內","Hunei","湖内","湖內","湖內","湖內","湖内" +"C0V650","彌陀","Mituo","弥陀","彌陀","彌陀","彌陀","弥陀" +"C0V660","岡山","Gangshan","岡山","岡山","岡山","岡山","冈山" +"C0V680","仁武","Renwu","仁武","仁武","仁武","仁武","仁武" +"C0V690","鼓山","Gushan","鼓山","鼓山","鼓山","鼓山","鼓山" +"C0V700","三民","Sanmin","三民","三民","三民","三民","三民" +"C0V710","苓雅","Lingya","苓雅","苓雅","苓雅","苓雅","苓雅" +"C0V720","林園","Linyuan","林園","林園","林園","林園","林园" +"C0V730","大寮","Daliao","大寮","大寮","大寮","大寮","大寮" +"C0V740","旗山","Qishan","旗山","旗山","旗山","旗山","旗山" +"C0V750","路竹","Luzhu","路竹","路竹","路竹","路竹","路竹" +"C0V760","橋頭","Qiaotou","橋頭","橋頭","橋頭","橋頭","桥头" +"C0V770","大社","Dashe","大社","大社","大社","大社","大社" +"C0V790","萬山","Wanshan","萬山","萬山","萬山","萬山","万山" +"C0V800","六龜","Liugui","六亀","六龜","六龜","六龜","六龟" +"C0V810","左營","Zuoying","左営","左營","左營","左營","左营" +"C0V820","小林","Xiaolin","小林","小林","小林","小林","小林" +"C0V840","鳳鼻頭","Fongbitou","鳳鼻頭","鳳鼻頭","鳳鼻頭","鳳鼻頭","凤鼻头" +"C0V850","蚵仔寮","Kezailiao","蚵仔寮","蚵仔寮","蚵仔寮","蚵仔寮","蚵仔寮" +"C0V860","南寮","Nanliao","南寮","南寮","南寮","南寮","南寮" +"C0V870","文安","Wunan","文安","文安","文安","文安","文安" +"C0V880","興達","Singda","興達","興達","興達","興達","兴达" +"C0V890","前鎮","Chian Jhen","前鎮","前鎮","前鎮","前鎮","前镇" +"C0V900","汕尾","Shanwei","汕尾","汕尾","汕尾","汕尾","汕尾" +"C0V910","大樹","Dashu","大樹","大樹","大樹","大樹","大树" +"C0W110","東莒","Dongju","東莒","東莒","東莒","東莒","东莒" +"C0W120","西嶼","Xiyu","西嶼","西嶼","西嶼","西嶼","西屿" +"C0W130","花嶼","Huayu","花嶼","花嶼","花嶼","花嶼","花屿" +"C0W140","金沙","Jinsha ","金沙","金沙","金沙","金沙","金沙" +"C0W150","金寧","Jinning","金寧","金寧","金寧","金寧","金宁" +"C0W160","烏坵","Wuqiu","烏坵","烏坵","烏坵","烏坵","乌坵" +"C0W180","七美","Qimei","七美","七美","七美","七美","七美" +"C0W190","望安","Wangan","望安","望安","望安","望安","望安" +"C0W200","湖西","Husi","湖西","湖西","湖西","湖西","湖西" +"C0W220","北竿","Beigan","北竿","北竿","北竿","北竿","北竿" +"C0W240","九宮","Jiugong ","九宮","九宮","九宮","九宮","九宫" +"C0X050","東河","Donghe","東河","東河","東河","東河","东河" +"C0X060","下營","Xiaying","下営","下營","下營","下營","下营" +"C0X080","佳里","Jiali","佳里","佳里","佳里","佳里","佳里" +"C0X100","臺南市北區","Beiqu Tainan City","臺南市北區","臺南市北區","臺南市北區","臺南市北區","台南市北区" +"C0X110","臺南市南區","Nanqu Tainan City","臺南市南區","臺南市南區","臺南市南區","臺南市南區","台南市南区" +"C0X120","麻豆","Madou","麻豆","麻豆","麻豆","麻豆","麻豆" +"C0X130","官田","Guantian","官田","官田","官田","官田","官田" +"C0X140","西港","Xigang","西港","西港","西港","西港","西港" +"C0X150","安定","Anding","安定","安定","安定","安定","安定" +"C0X160","仁德","Rende","仁徳","仁德","仁德","仁德","仁德" +"C0X170","關廟","Guanmiao","関廟","關廟","關廟","關廟","关庙" +"C0X180","山上","Shanshang","山上","山上","山上","山上","山上" +"C0X190","安平","Anping","安平","安平","安平","安平","安平" +"C0X200","左鎮","Zuozhen","左鎮","左鎮","左鎮","左鎮","左镇" +"C0X210","白河","Baihe","白河","白河","白河","白河","白河" +"C0X220","學甲","Xuejia","学甲","學甲","學甲","學甲","学甲" +"C0X230","鹽水","Yanshui","塩水","鹽水","鹽水","鹽水","盐水" +"C0X240","關子嶺","Guanziling","關子嶺","關子嶺","關子嶺","關子嶺","关子岭" +"C0X250","新營","Xinying","新営","新營","新營","新營","新营" +"C0X260","後壁","Houbi","後壁","後壁","後壁","後壁","后壁" +"C0X280","將軍","Jiangjun","将軍","將軍","將軍","將軍","将军" +"C0X290","北門","Beimen","北門","北門","北門","北門","北门" +"C0X300","鹿寮","Luliao","鹿寮","鹿寮","鹿寮","鹿寮","鹿寮" +"C0X320","柳營","Liuying","柳営","柳營","柳營","柳營","柳营" +"C0Z020","明里","Mingli","明里","明里","明里","明里","明里" +"C0Z050","佳心","Jiaxin","佳心","佳心","佳心","佳心","佳心" +"C0Z061","玉里","Yuli","玉里","玉里","玉里","玉里","玉里" +"C0Z070","舞鶴","Wuhe","舞鶴","舞鶴","舞鶴","舞鶴","舞鹤" +"C0Z080","富源","Fuyuan","富源","富源","富源","富源","富源" +"C0Z100","東華","Donghwa","東華","東華","東華","東華","东华" +"C0Z150","吉安光華","Guanghua Ji-An","吉安光華","吉安光華","吉安光華","吉安光華","吉安光华" +"C0Z160","鳳林","Fenglin","鳳林","鳳林","鳳林","鳳林","凤林" +"C0Z170","卓溪","Zhuoxi","卓渓","卓溪","卓溪","卓溪","卓溪" +"C0Z180","新城","Xincheng","新城","新城","新城","新城","新城" +"C0Z190","富世","Fushi","富世","富世","富世","富世","富世" +"C0Z200","萬榮","Wanrong","万栄","萬榮","萬榮","萬榮","万荣" +"C0Z210","瑞穗","Ruisui","瑞穂","瑞穗","瑞穗","瑞穗","瑞穗" +"C0Z220","和平林道","Hepinglindao","和平林道","和平林道","和平林道","和平林道","和平林道" +"C0Z230","和平","Heping","和平","허핑","和平","和平","和平" +"C0Z250","瑞穗林道","Ruisuilindao","瑞穗林道","瑞穗林道","瑞穗林道","瑞穗林道","瑞穗林道" +"C0Z270","蕃薯寮","Fanshuliao","蕃薯寮","蕃薯寮","蕃薯寮","蕃薯寮","蕃薯寮" +"C0Z280","德武","Dewu","德武","德武","德武","德武","德武" +"C0Z290","赤柯山","Chikeshan","赤柯山","赤柯山","赤柯山","赤柯山","赤柯山" +"C0Z300","東里","Dongli","東里","東里","東里","東里","东里" +"C0Z310","清水斷崖","Qingshui Cliff","清水斷崖","清水斷崖","清水斷崖","清水斷崖","清水断崖" +"C0Z320","清水林道","Qingshuilindao","清水林道","清水林道","清水林道","清水林道","清水林道" +"C0Z330","安通山","Antongshan","安通山","安通山","安通山","安通山","安通山" +"C1A630","下盆","Siapen","下盆","下盆","下盆","下盆","下盆" +"C1A750","石碇服務區","Shiding Service Area","石碇服務區","石碇服務區","石碇服務區","石碇服務區","石碇服务区" +"C1A760","坪林交控","Pinglin Traffic Control Center","坪林交控","坪林交控","坪林交控","坪林交控","坪林交控" +"C1A9N0","四十份","Sihshihfen","四十份","四十份","四十份","四十份","四十份" +"C1AC50","關渡","Guandu","關渡","關渡","關渡","關渡","关渡" +"C1AI50","國三N016K","Freeway No. 3 - Rain - N016k","國三N016K","國三N016K","國三N016K","國三N016K","国三N016K" +"C1AI60","國一39K邊坡","Freeway No. 1 - Rain – N039k","國一39K邊坡","國一39K邊坡","國一39K邊坡","國一39K邊坡","国一39K边坡" +"C1C510","水尾","Shueiwei","水尾","水尾","水尾","水尾","水尾" +"C1D380","新埔","Sinpu","新埔","新埔","新埔","新埔","新埔" +"C1D400","鳥嘴山","Niaozueishan","鳥嘴山","鳥嘴山","鳥嘴山","鳥嘴山","鸟嘴山" +"C1D410","白蘭","Bailan","白蘭","白蘭","白蘭","白蘭","白兰" +"C1D420","太閣南","Taigenan","太閣南","太閣南","太閣南","太閣南","太阁南" +"C1D630","飛鳳山","Fei Feng Mountain","飛鳳山","飛鳳山","飛鳳山","飛鳳山","飞凤山" +"C1D640","外坪(五指山)","Waiping(Wuzhihshan)","外坪(五指山)","外坪(五指山)","外坪(五指山)","外坪(五指山)","外坪(五指山)" +"C1E451","象鼻","Xiangbi","象鼻","象鼻","象鼻","象鼻","象鼻" +"C1E461","松安","Song-An","松安","松安","松安","松安","松安" +"C1E480","鳳美","Fongmei","鳳美","鳳美","鳳美","鳳美","凤美" +"C1E511","新開","Xinkai","新開","新開","新開","新開","新开" +"C1E601","南勢","Nanshi","南勢","南勢","南勢","南勢","南势" +"C1E670","南礦","Nankuang","南礦","南礦","南礦","南礦","南矿" +"C1E681","南勢山","Nanshishan","南勢山","南勢山","南勢山","南勢山","南势山" +"C1E691","南湖","Nanhu","南湖","南湖","南湖","南湖","南胡" +"C1E701","八卦","Bagua","八卦","八卦","八卦","八卦","八卦" +"C1E711","馬拉邦山","Malabangshan","馬拉邦山","馬拉邦山","馬拉邦山","馬拉邦山","馬拉邦山" +"C1E721","泰安","Tai-An","泰安","泰安","泰安","泰安","泰安" +"C1E770","公館","Gongguan","公館","公館","公館","公館","公馆" +"C1E890","國三N149K","Freeway No. 1 - Rain – N149k","國三N149K","國三N149K","國三N149K","國三N149K","国三N149K" +"C1E900","國一N128K","Freeway No. 1 - Rain – N128k","國一N128K","國一N128K","國一N128K","國一N128K","国一N128K" +"C1F871","上谷關","Shangguguan","上谷關","上谷關","上谷關","上谷關","上谷关" +"C1F891","稍來","Shaolai","稍來","稍來","稍來","稍來","稍来" +"C1F911","新伯公","Xinbogong","新伯公","新伯公","新伯公","新伯公","新伯公" +"C1F941","雪嶺","Xueling","雪嶺","雪嶺","雪嶺","雪嶺","雪岭" +"C1F9B1","桐林","Tonglin","桐林","桐林","桐林","桐林","桐林" +"C1F9C1","白冷","Baileng","白冷","白冷","白冷","白冷","白冷" +"C1F9D1","白毛台","Baimaotai","白毛台","白毛台","白毛台","白毛台","白毛台" +"C1F9E1","龍安","Long-An","龍安","龍安","龍安","龍安","龙安" +"C1F9F1","伯公龍","Bogonglong","伯公龍","伯公龍","伯公龍","伯公龍","伯公龙" +"C1F9G1","慶福山","Cingfushan","慶福山","慶福山","慶福山","慶福山","庆福山" +"C1F9J1","清水林","Qingshuilin","清水林","清水林","清水林","清水林","清水林" +"C1F9W0","德基","Deji","德基","德基","德基","德基","德基" +"C1G691","下水埔","Xiashuipu","下水埔","下水埔","下水埔","下水埔","下水埔" +"C1G9D0","國一S218K","Freeway No. 1 - Rain – S218k","國一S218K","國一S218K","國一S218K","國一S218K","國一S218K" +"C1H000","翠峰","Cuifeng","翠峰","翠峰","翠峰","翠峰","翠峰" +"C1H840","國三N238K","Freeway No. 3 - Rain –N238k","國三N238K","國三N238K","國三N238K","國三N238K","國三N238K" +"C1H900","清流","Qingliu","清流","清流","清流","清流","清流" +"C1H920","長豐","Changfeng","長豐","長豐","長豐","長豐","长丰" +"C1H941","雙冬","Shuangdong","雙冬","雙冬","雙冬","雙冬","双冬" +"C1H971","六分寮","Liufenliao","六分寮","六分寮","六分寮","六分寮","六分寮" +"C1H9B1","阿眉","Amei","阿眉","阿眉","阿眉","阿眉","阿眉" +"C1I020","萬大","Wanda","萬大","萬大","萬大","萬大","万大" +"C1I030","武界","Wujie","武界","武界","武界","武界","武界" +"C1I050","丹大","Danda","丹大","丹大","丹大","丹大","丹大" +"C1I070","和社","Heshe","和社","和社","和社","和社","和社" +"C1I101","溪頭","Xitou","溪頭","溪頭","溪頭","溪頭","溪头" +"C1I121","大鞍","Da-An","大鞍","大鞍","大鞍","大鞍","大鞍" +"C1I131","桶頭","Tongtou","桶頭","桶頭","桶頭","桶頭","桶头" +"C1I140","卡奈托灣","Kanaituowan","卡奈托灣","卡奈托灣","卡奈托灣","卡奈托灣","卡奈托湾" +"C1I150","青雲","Qingyun","青雲","青雲","青雲","青雲","青云" +"C1I201","中心崙","Zhongxinlun","中心崙","中心崙","中心崙","中心崙","中心仑" +"C1I211","蘆竹湳","Luzhunan","蘆竹湳","蘆竹湳","蘆竹湳","蘆竹湳","芦竹湳" +"C1I220","樟湖","Zhanghu","樟湖","樟湖","樟湖","樟湖","樟湖" +"C1I230","九份二山","Jiufen'Ershan","九份二山","九份二山","九份二山","九份二山","九份二山" +"C1I240","外大坪","Waidaping","外大坪","外大坪","外大坪","外大坪","外大坪" +"C1I250","鯉潭","Litan","鯉潭","鯉潭","鯉潭","鯉潭","鲤潭" +"C1I260","北坑","Beikeng","北坑","北坑","北坑","北坑","北坑" +"C1I280","埔中","Puzhong","埔中","埔中","埔中","埔中","埔中" +"C1I290","豐丘","Fengqiu","豐丘","豐丘","豐丘","豐丘","丰丘" +"C1I310","西巒","Xiluan","西巒","西巒","西巒","西巒","西峦" +"C1I320","奧萬大","Aowanda","奧萬大","奧萬大","奧萬大","奧萬大","奥万大" +"C1I330","楓樹林","Fengshulin","楓樹林","楓樹林","楓樹林","楓樹林","枫树林" +"C1I340","新興橋","Xinxingqiao","新興橋","新興橋","新興橋","新興橋","新兴桥" +"C1I400","凌霄","Lingxiao","凌霄","凌霄","凌霄","凌霄","凌霄" +"C1I430","翠華","Cuihua","翠華","翠華","翠華","翠華","翠华" +"C1I440","新高口","Xingaokou","新高口","新高口","新高口","新高口","新高口" +"C1I450","望鄉山","Wangxiangshan","望鄉山","望鄉山","望鄉山","望鄉山","望乡山" +"C1I470","杉林溪","Shanlinxi","杉林溪","杉林溪","杉林溪","杉林溪","杉林溪" +"C1I500","大尖山","Dajianshan","大尖山","大尖山","大尖山","大尖山","大尖山" +"C1I510","線浸林道","Xianjinlindao","線浸林道","線浸林道","線浸林道","線浸林道","线浸林道" +"C1I550","國六W023K","Freeway No. 6 - Rain – W023k","國六W023K","國六W023K","國六W023K","國六W023K","国六W023K" +"C1K540","口湖","Kouhu","口湖","口湖","口湖","口湖","口湖" +"C1M390","龍美","Longmei","龍美","龍美","龍美","龍美","龙美" +"C1M400","菜瓜坪","Caiguaping","菜瓜坪","菜瓜坪","菜瓜坪","菜瓜坪","菜瓜坪" +"C1M480","獨立山","Dulishan","獨立山","獨立山","獨立山","獨立山","独立山" +"C1M600","頭凍","Toudong","頭凍","頭凍","頭凍","頭凍","头冻" +"C1M610","石磐龍","Shipanlong","石磐龍","石磐龍","石磐龍","石磐龍","石磐龙" +"C1M640","十字","Shizi","十字","十字","十字","十字","十字" +"C1M870","國三N285K","Freeway No. 3 - Rain –N285k","國三N285K","國三N285K","國三N285K","國三N285K","国三N285K" +"C1N001","沙崙","Shalun","沙崙","沙崙","沙崙","沙崙","沙仑" +"C1O850","環湖","Huanhu","環湖","環湖","環湖","環湖","环湖" +"C1O870","大棟山","Dadongshan","大棟山","大棟山","大棟山","大棟山","大栋山" +"C1O880","關山","Guanshan","関山","關山","關山","關山","关山" +"C1O921","楠西","Nanxi","楠西","楠西","楠西","楠西","楠西" +"C1O940","東山服務區","Dongshan Service Area","東山服務區","東山服務區","東山服務區","東山服務區","东山服务区" +"C1R110","口社","Gusia","口社","口社","口社","口社","口社" +"C1R120","上德文","Shangdewun","上德文","上德文","上德文","上德文","上德文" +"C1R250","力里","Lili","力里","力里","力里","力里","力里" +"C1R290","石門山","Shihmenshan","石門山","石門山","石門山","石門山","石门山" +"C1R610","西大武山","Xidawushan","西大武山","西大武山","西大武山","西大武山","西大武山" +"C1R630","龍泉","Longquan","龍泉","龍泉","龍泉","龍泉","龙泉" +"C1S670","摩天","Motian","摩天","摩天","摩天","摩天","摩天" +"C1S800","華源","Huayuan","華源","華源","華源","華源","华源" +"C1S820","金峰","Jinfeng","金峰","金峰","金峰","金峰","金峰" +"C1S850","豐南","Funan","豐南","豐南","豐南","豐南","丰南" +"C1S860","利嘉","Lichai","利嘉","利嘉","利嘉","利嘉","利嘉" +"C1S870","南美山","Nanmaisan","南美山","南美山","南美山","南美山","南美山" +"C1S880","壽卡","Shouka","壽卡","壽卡","壽卡","壽卡","寿卡" +"C1SA50","利嘉林道","Lijialindao","利嘉林道","利嘉林道","利嘉林道","利嘉林道","利嘉林道" +"C1SA70","都蘭","Dulan","都蘭","都蘭","都蘭","都蘭","都兰" +"C1T800","洛韶","Luoshao","洛韶","洛韶","洛韶","洛韶","洛韶" +"C1T810","慈恩","Ci-En","慈恩","慈恩","慈恩","慈恩","慈恩" +"C1T830","布洛灣","Buluowan","布洛灣","布洛灣","布洛灣","布洛灣","布洛湾" +"C1T920","中興","Zhongxing","中興","中興","中興","中興","中兴" +"C1T940","大觀","Daguan","大觀","大觀","大觀","大觀","大观" +"C1T950","太安","Tai-An","太安","太安","太安","太安","太安" +"C1T970","大農","Danong","大農","大農","大農","大農","大农" +"C1T980","龍澗","Longjian","龍澗","龍澗","龍澗","龍澗","龙涧" +"C1T990","高寮","Gaoliao","高寮","高寮","高寮","高寮","高寮" +"C1TA00","太魯閣","Taroko","太魯閣","太魯閣","太魯閣","太魯閣","太鲁阁" +"C1U501","牛鬥","Nioudou","牛鬥","牛鬥","牛鬥","牛鬥","牛斗" +"C1U670","寒溪","Hanxi","寒溪","寒溪","寒溪","寒溪","寒溪" +"C1U840","東澳嶺","Dongaoling","東澳嶺","東澳嶺","東澳嶺","東澳嶺","东澳岭" +"C1U850","觀音海岸","Guanyin Coast","觀音海岸","觀音海岸","觀音海岸","觀音海岸","观音海岸" +"C1U920","思源","Siyuan","思源","思源","思源","思源","思源" +"C1U930","粉鳥林","Fenniaolin","粉鳥林","粉鳥林","粉鳥林","粉鳥林","粉鸟林" +"C1V160","達卡努瓦","Dakanuwa","達卡努瓦","達卡努瓦","達卡努瓦","達卡努瓦","达卡努瓦" +"C1V170","排雲","Paiyun","排雲","排雲","排雲","排雲","排云" +"C1V190","南天池","Nantianchi","南天池","南天池","南天池","南天池","南天池" +"C1V200","梅山","Meishan","梅山","梅山","梅山","梅山","梅山" +"C1V220","小關山","Xiaoguanshan","小關山","小關山","小關山","小關山","小关山" +"C1V231","高中","Gaozhong","高中","高中","高中","高中","高中" +"C1V300","御油山","Yuyoushan","御油山","御油山","御油山","御油山","御油山" +"C1V340","大津","Dajin","大津","大津","大津","大津","大津" +"C1V390","尖山","Jianshan","尖山","尖山","尖山","尖山","尖山" +"C1V570","吉東","Jiadong","吉東","吉東","吉東","吉東","吉东" +"C1V580","溪南(特生中心)","Xinan","溪南(特生中心)","溪南(特生中心)","溪南(特生中心)","溪南(特生中心)","溪南(特生中心)" +"C1V590","新發","Xinfa","新發","新發","新發","新發","新发" +"C1V600","藤枝","Tengzhi","藤枝","藤枝","藤枝","藤枝","藤枝" +"C1V780","多納林道","Duonalindao","多納林道","多納林道","多納林道","多納林道","多纳林道" +"C1V830","國三S383K","Freeway No. 3 - Rain – S383k","國三S383K","國三S383K","國三S383K","國三S383K","國三S383K" +"C1X040","東原","Dongyuan","東原","東原","東原","東原","东原" +"C1Z030","紅葉","Hongye","紅葉","紅葉","紅葉","紅葉","红叶" +"C1Z040","立山","Lishan","立山","立山","立山","立山","立山" +"C1Z110","三棧","Sanzhan","三棧","三棧","三棧","三棧","三栈" +"C1Z120","壽豐","Shoufeng","寿豊","壽豐","壽豐","壽豐","寿丰" +"C1Z130","銅門","Tongmen","銅門","銅門","銅門","銅門","铜门" +"C1Z140","荖溪","Laoxi","荖溪","荖溪","荖溪","荖溪","荖溪" +"C1Z240","中平林道","Zhongpinglindao","中平林道","中平林道","中平林道","中平林道","中平林道" diff --git a/assets/translations/zh-Hans.po b/assets/translations/zh-Hans.po index 8faaaa2ce..0dbb5675b 100644 --- a/assets/translations/zh-Hans.po +++ b/assets/translations/zh-Hans.po @@ -4,18 +4,22 @@ msgstr "" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: zh-CN\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" -"X-Crowdin-File-ID: 20\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 26\n" "Project-Id-Version: dpip\n" "Content-Type: text/plain; charset=UTF-8\n" "Language-Team: Chinese Simplified\n" "Language: zh_CN\n" -"PO-Revision-Date: 2025-07-23 03:45\n" +"PO-Revision-Date: 2025-09-01 03:16\n" -#: ./lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "所在地" +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "新增地点" + #: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "主题" @@ -28,23 +32,23 @@ msgstr "语言" msgid "單位" msgstr "单位" -#: ./lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "地图" -#: ./lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "通知" -#: ./lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "紧急地震预警" -#: ./lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" msgstr "强震监视器" -#: ./lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "地震报告" @@ -61,10 +65,10 @@ msgid "天氣警特報" msgstr "天气警特报" #: ./lib/app/settings/notify/page.dart:236 -msgid "避難資訊" -msgstr "避难信息" +msgid "防災資訊" +msgstr "防灾资讯" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" msgstr "海啸信息" @@ -80,11 +84,11 @@ msgstr "赞助我们" msgid "設定" msgstr "设置" -#: ./lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "接收全部" -#: ./lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "关闭" @@ -92,23 +96,23 @@ msgstr "关闭" msgid "接收類別" msgstr "接收类别" -#: ./lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" msgstr "所在地震度1以上" -#: ./lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" msgstr "海啸信息、海啸警报" -#: ./lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "只接收海啸警报" -#: ./lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "接收所在地" -#: ./lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" msgstr "所在地震度4以上" @@ -120,7 +124,7 @@ msgstr "音效测试" msgid "發送公告時" msgstr "发送公告时" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" msgstr "音效测试是在设备上执行的本地通知,仅用于确认设备在接收通知时是否能正常播放音效。此测试不会向服务器发送任何请求" @@ -132,7 +136,7 @@ msgstr "请先设置所在地以使用通知功能" msgid "地震速報" msgstr "地震预警" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "地震" @@ -140,7 +144,7 @@ msgstr "地震" msgid "天氣" msgstr "天气" -#: ./lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "海啸" @@ -148,25 +152,21 @@ msgstr "海啸" msgid "其他" msgstr "其他" -#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "重大" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "海嘯警報發布時\n" -"沿海地區鄉鎮" -msgstr "海啸警报发布时\n" -"沿海地区乡镇" +msgid "海嘯警報發布時" +msgstr "海啸警报发布时" -#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "常规​​​​​" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "海嘯警報發布時\n" -"上述除外地區" -msgstr "海啸警报发布时\n" -"上述除外地区" +msgid "海嘯消息發布時" +msgstr "海啸信息发布时" #: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息(無聲通知)" @@ -279,12 +279,12 @@ msgid "所在地(鄉鎮)預估震度 1 以上" msgstr "所在地(乡镇)预估震度 1 以上" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" -msgstr "所在地(乡镇)发布避难警报时" +msgid "所在地(鄉鎮)發布防災警訊時" +msgstr "所在地(乡镇)发布防灾警讯时" #: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" -msgstr "所在地(乡镇)发布避难信息时" +msgid "所在地(鄉鎮)發布防災資訊時" +msgstr "所在地(乡镇)发布防灾资讯时" #: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 msgid "所在地(鄉鎮)發布紅色燈號之\n" @@ -299,10 +299,12 @@ msgstr "所在地(乡镇)发布上述除外灯信号的\n" "天气警特报" #: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" -msgstr "所在地(乡镇)发布雷雨即时信息或\n" -"山区暴雨时" +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "所在地(乡镇)发布山区暴雨时" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" +msgstr "所在地(乡镇)发布雷雨即时信息时" #: ./lib/app/settings/unit/page.dart:28 msgid "使用華氏度" @@ -340,60 +342,61 @@ msgstr "已翻译 {translated}・已校对 {approved}" msgid "來源語言" msgstr "来源语言" -#: ./lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "无法连接到商店,请稍后再试" -#: ./lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "找不到商品,请稍后再试" -#: ./lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "重新加载" -#: ./lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "正在加载商店商品中" -#: ./lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n" "您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" -msgstr "" +msgstr "DPIP 作为一款致力于提供及时地震信息的app,目前并无广告或其他盈利模式。为了维持高质量服务,我们需要承担服务器运行,地震信息获取与传输、以及后续功能开发与维护的成本!\n\n" +"您在下方所选择的每一份支持,都将直接用于支付这些营运费用,帮助 DPIP 持续稳定底,为您提供服务。感谢您的理解与慷慨!" -#: ./lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "订阅制" -#: ./lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "{price}/月" -#: ./lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "单次支持" -#: ./lib/app/settings/donate/page.dart:197 +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" -msgstr "" +msgstr "无法连接至 {store} ,请稍后再试。" -#: ./lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" -msgstr "" +msgstr "正在恢复您购买的订阅" -#: ./lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" -msgstr "" +msgstr "恢复购买" -#: ./lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" -msgstr "" +msgstr "使用条款" -#: ./lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" -msgstr "" +msgstr "隐私权政策" -#: ./lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "位置" @@ -477,53 +480,165 @@ msgstr "App 日志" msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "任何信息应以中央气象署发布内容为准。" -#: ./lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "无法取得通知权限" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "无法取得位置权限" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "无法获取自启动权限" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "省电策略" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "无法取得权限" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "自动定位功能需要您允许 DPIP 使用通知权限才能正常运作。请您到应用程式设定中找到并允许「通知」权限后再试一次。" + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "自动定位功能需要您允许 DPIP 使用位置权限才能正常运作。请您到应用程式设定中找到并允许「位置」权限后再试一次。" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "自动定位功能需要您永远允许 DPIP 使用位置权限才能正常运作。请您到应用程式设定中找到位置权限设定并选择「永远」后再试一次。" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "自动定位功能需要您一律允许 DPIP 使用位置权限才能正常运作。请您到应用程式设定中找到位置权限设定并选择「一律允许」后再试一次。" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "为了获得更好的自动定位体验,您需要给予「自启动权限」以便让 DPIP 在背景自动设定所在地资讯。" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "为了获得更好的自动定位体验,您需要授予「无限制」以便让 DPIP 在后台自动设置所在地信息。" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "自动定位功能需要您允许 DPIP 使用权限才能正常运作。请您到应用程式设定中找到并允许「权限」后再试一次。" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "取消" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "自动启动" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "为了获得更好的 DPIP 体验,请依照步骤启用自动启动功能,以便让 DPIP 在背景能正常接收资讯以及更新所在地。" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "为了获得更好的 DPIP 体验,请依照步骤关闭省电策略,以便让 DPIP 在背景能正常接收资讯以及更新所在地。" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "始终允许" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "永远" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "自动更新" -#: ./lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "定期更新当前位置" -#: ./lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "自动定位功能会使用您设备上的 GPS,即使 DPIP 处于关闭或未使用状态,也会根据您的地理位置自动更新当前所在位置,提供实时天气与地震信息,助您随时掌握本地最新动态。" -#: ./lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" -msgstr "直辖市/县市" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" +msgstr "通知功能已被拒绝,请前往设置允许权限。" -#: ./lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" -msgstr "尚未设置" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" +msgstr "自启动权限已被拒绝,请移至设置开启权限。" + +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" +msgstr "省电策略被拒绝,请前往设置允许权限。" -#: ./lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" -msgstr "乡镇市区" +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" +msgstr "设置所在地时发生错误,请稍后再试。" -#: ./lib/app/settings/location/select/page.dart:26 +#: ./lib/app/settings/location/select/page.dart:38 msgid "縣市" msgstr "县市" -#: ./lib/app/settings/location/select/page.dart:38 +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "当前位置" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "监视器" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "雷达拼图" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "气温" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "降水" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "风向/风速" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "简单" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "Google" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "底图" -#: ./lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "默认图层" -#: ./lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" -msgstr "" +msgstr "动画帧率" -#: ./lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "影响强震监视器的地震波模拟动画流畅度" + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" -msgstr "" +msgstr "过高的动画帧率可能会造成设备卡顿或发热" #: ./lib/app/settings/theme/page.dart:30 msgid "主題模式" @@ -553,10 +668,6 @@ msgstr "系统颜色" msgid "使用系統顏色" msgstr "使用系统颜色" -#: ./lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "取消" - #: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "确定" @@ -569,9 +680,9 @@ msgstr "您所在区域附近正发生强雷雨或降雨,请注意防范,预 msgid "服務區域外,僅在臺灣各地可用" msgstr "服务区域外,仅在台湾各地可用" -#: ./lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" -msgstr "雷达拼图" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" +msgstr "尚未设置" #: ./lib/app/home/_widgets/weather_header.dart:127 msgid "體感約 {apparent}°" @@ -581,31 +692,39 @@ msgstr "体感约 {apparent}°" msgid "尚未設定所在地" msgstr "尚未设定所在地" -#: ./lib/app/map/_lib/managers/monitor.dart:874 -msgid "第 {serial} 報" +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" msgstr "" -#: ./lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1089 +msgid "第 {serial} 報" +msgstr "第 {serial} 报" + +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。" -msgstr "" +msgstr "{time} 左右,{location}附近发生有感地震,预计规模 M{magnitude}、所在地最大震度{intensity}。" -#: ./lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。" +msgstr "{time} 左右,{location}附近发生有感地震,预计规模 M{magnitude}、深度{depth}公里。" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" -msgstr "" +msgstr "所在地预估" -#: ./lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" -msgstr "" +msgstr "震波" -#: ./lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" -msgstr "" +msgstr " 秒" -#: ./lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" -msgstr "" +msgstr "抵达" -#: ./lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" msgstr "已更新至 {version}" @@ -621,7 +740,7 @@ msgstr "无法载入更新日志,请稍后再试。" msgid "重試" msgstr "重试" -#: ./lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "下一步" @@ -673,19 +792,15 @@ msgstr "欢迎使用 DPIP" msgid "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "DPIP 是一款由台湾本土团队设计的 App,集成 TREM-Net (台湾即时地震观测网) 的信息及中央气象署数据,提供一个集成、单一且便利的防灾信息应用。" -#: ./lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "在重大灾害发生时以通知来传递即时防灾信息" -#: ./lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" msgstr "使用定位来自动更新所在地设置,提供当地的即时防灾信息" -#: ./lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "省电策略" - -#: ./lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "允许DPIP在后台持续运行,以便获取实时防灾通知。" @@ -693,293 +808,305 @@ msgstr "允许DPIP在后台持续运行,以便获取实时防灾通知。" msgid "儲存" msgstr "储存" -#: ./lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "用于存储中央气象署或 ExpTech 提供的数据可视化图片" -#: ./lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "权限请求" -#: ./lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "需要用户手动前往设置开启相关权限。" -#: ./lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "权限" -#: ./lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "我们一直和用户站在一起,为用户的隐私而不断努力。" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "地图图层" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "选择要显示的地图图层" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" -msgstr "线条" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" +msgstr "报告" -#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "气象" -#: ./lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "气温" - -#: ./lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "降水" - -#: ./lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "风向/风速" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" +msgstr "单位:{unit}" -#: ./lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" -msgstr "" +msgstr "长按设定播放起点" -#: ./lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" -msgstr "" +msgstr "目前时间" -#: ./lib/app/map/_lib/managers/radar.dart:632 +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" -msgstr "" +msgstr "播放起点" -#: ./lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" -msgstr "" +msgstr "播放进度" -#: ./lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "今天" -#: ./lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" msgstr "10 分钟" -#: ./lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" msgstr "1 小时" -#: ./lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" msgstr "3 小时" -#: ./lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" msgstr "6 小时" -#: ./lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" msgstr "12 小时" -#: ./lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" msgstr "24 小时" -#: ./lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" msgstr "2 天" -#: ./lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" msgstr "3 天" -#: ./lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "海外测站" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "实时震度:" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "地动加速度:" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "地动速度:" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "无数据" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" -msgstr "" +msgstr "目前没有生效中的地震预警" -#: ./lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" +msgstr "规模 M{magnitude}、深度{depth}公里" + +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" -msgstr "" +msgstr "规模 M{magnitude},所在地预估{intensity}" -#: ./lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" -msgstr "" +msgstr "{countdown}秒后抵达" -#: ./lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" -msgstr "" +msgstr "已抵达" -#: ./lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" msgstr "近期地震报告" -#: ./lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "更多" -#: ./lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" msgstr "序号 {number} 显著有感地震" -#: ./lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "小区域有感地震" -#: ./lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "地震震级" -#: ./lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "震源深度" -#: ./lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "报告详情" -#: ./lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" msgstr "发震时刻" -#: ./lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "位于" -#: ./lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "各地震度" -#: ./lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "地震报告图" -#: ./lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "震度图" -#: ./lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "峰值地震动加速度图" -#: ./lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "峰值最大地震动速度图" #: ./lib/route/announcement/announcement.dart:12 msgid "錯誤" -msgstr "" +msgstr "错误" #: ./lib/route/announcement/announcement.dart:13 msgid "已解決" -msgstr "" +msgstr "已解决" #: ./lib/route/announcement/announcement.dart:14 msgid "影響:小" -msgstr "" +msgstr "影响:小" #: ./lib/route/announcement/announcement.dart:15 msgid "影響:中" -msgstr "" +msgstr "影响:中" #: ./lib/route/announcement/announcement.dart:16 msgid "影響:大" -msgstr "" +msgstr "影响:大" #: ./lib/route/announcement/announcement.dart:18 msgid "維修" -msgstr "" +msgstr "维护" #: ./lib/route/announcement/announcement.dart:19 msgid "測試" -msgstr "" +msgstr "测试" #: ./lib/route/announcement/announcement.dart:20 msgid "變更" -msgstr "" +msgstr "变更" #: ./lib/route/announcement/announcement.dart:21 msgid "完成" -msgstr "" +msgstr "完成" #: ./lib/route/announcement/announcement.dart:22 msgid "地震相關" -msgstr "" +msgstr "地震相关信息" #: ./lib/route/announcement/announcement.dart:23 msgid "氣象相關" -msgstr "" +msgstr "气象相关信息" #: ./lib/route/announcement/announcement.dart:29 msgid "未知" -msgstr "" +msgstr "未知" #: ./lib/route/announcement/announcement.dart:103 msgid "目前沒有公告" -msgstr "" +msgstr "目前没有通知" #: ./lib/route/announcement/announcement.dart:223 msgid "公告詳情" -msgstr "" - -#: ./lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "" +msgstr "通知详情" #: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" -msgstr "" +msgstr "请领导应用程序设定中找到并允许「相片和媒体」权限后在试一次。" #: ./lib/route/image_viewer/image_viewer.dart:70 msgid "再試一次" -msgstr "" +msgstr "再试一次" #: ./lib/route/image_viewer/image_viewer.dart:110 msgid "已儲存圖片" -msgstr "" +msgstr "已存储图片" #: ./lib/route/image_viewer/image_viewer.dart:126 msgid "儲存圖片時發生錯誤" -msgstr "" +msgstr "存储图片时发生错误" #: ./lib/utils/extensions/int.dart:13 msgid "0級" -msgstr "" +msgstr "0级" #: ./lib/utils/extensions/int.dart:14 msgid "1級" -msgstr "" +msgstr "1级" #: ./lib/utils/extensions/int.dart:15 msgid "2級" -msgstr "" +msgstr "2级" #: ./lib/utils/extensions/int.dart:16 msgid "3級" -msgstr "" +msgstr "3级" #: ./lib/utils/extensions/int.dart:17 msgid "4級" -msgstr "" +msgstr "4级" #: ./lib/utils/extensions/int.dart:18 msgid "5弱" -msgstr "" +msgstr "5弱" #: ./lib/utils/extensions/int.dart:19 msgid "5強" -msgstr "" +msgstr "5强" #: ./lib/utils/extensions/int.dart:20 msgid "6弱" -msgstr "" +msgstr "6弱" #: ./lib/utils/extensions/int.dart:21 msgid "6強" -msgstr "" +msgstr "6强" #: ./lib/utils/extensions/int.dart:22 msgid "7級" -msgstr "" +msgstr "7级" #: ./lib/utils/weather_icon.dart:283 msgid "晴" @@ -1209,3 +1336,19 @@ msgstr "阴天有强雷阵雨" msgid "陰大雷雹" msgstr "阴天有强雷冰雹" +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "{city}{cityLevel} {town}{townLevel}" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "{city} {town}" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "{city}{cityLevel}" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "{town}{townLevel}" + diff --git a/assets/translations/zh-Hant.po b/assets/translations/zh-Hant.po index e29eb0d2b..e222f1ca7 100644 --- a/assets/translations/zh-Hant.po +++ b/assets/translations/zh-Hant.po @@ -1,242 +1,233 @@ msgid "" msgstr "" -"Project-Id-Version: dpip\n" -"PO-Revision-Date: 2025-06-17 15:33\n" -"Language-Team: Chinese Traditional\n" -"Language: zh_TW\n" -"Content-Type: text/plain; charset=UTF-8\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Crowdin-Project: dpip\n" "X-Crowdin-Project-ID: 696803\n" "X-Crowdin-Language: zh-TW\n" -"X-Crowdin-File: /main/assets/translations/strings.pot\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" "X-Crowdin-File-ID: 20\n" +"Project-Id-Version: dpip\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Language-Team: Chinese Traditional\n" +"Language: zh_TW\n" -#: lib/app/settings/location/page.dart:555 +#: ./lib/app/settings/location/page.dart:372 msgid "所在地" msgstr "所在地" -#: lib/app/settings/page.dart:52 +#: ./lib/app/settings/location/page.dart:421 +msgid "新增地點" +msgstr "新增地點" + +#: ./lib/app/settings/page.dart:52 msgid "主題" msgstr "主題" -#: lib/app/settings/page.dart:60 +#: ./lib/app/settings/page.dart:60 msgid "語言" msgstr "語言" -#: lib/app/settings/page.dart:68 +#: ./lib/app/settings/page.dart:68 msgid "單位" msgstr "單位" -#: lib/app/settings/map/page.dart:24 +#: ./lib/app/settings/map/page.dart:65 msgid "地圖" msgstr "地圖" -#: lib/app/welcome/4-permissions/page.dart:155 +#: ./lib/app/welcome/4-permissions/page.dart:153 msgid "通知" msgstr "通知" -#: lib/app/map/_lib/managers/monitor.dart:864 +#: ./lib/app/settings/notify/page.dart:148 msgid "緊急地震速報" msgstr "緊急地震速報" -#: lib/app/map/_lib/managers/monitor.dart:706 +#: ./lib/app/map/_lib/managers/monitor.dart:784 msgid "強震監視器" msgstr "強震監視器" -#: lib/app/map/_lib/managers/report.dart:814 +#: ./lib/app/map/_lib/managers/report.dart:818 msgid "地震報告" msgstr "地震報告" -#: lib/app/settings/notify/page.dart:192 +#: ./lib/app/settings/notify/page.dart:192 msgid "震度速報" msgstr "震度速報" -#: lib/app/home/_widgets/thunderstorm_card.dart:59 +#: ./lib/app/home/_widgets/thunderstorm_card.dart:59 msgid "雷雨即時訊息" msgstr "雷雨即時訊息" -#: lib/app/settings/notify/page.dart:223 +#: ./lib/app/settings/notify/page.dart:223 msgid "天氣警特報" msgstr "天氣警特報" -#: lib/app/settings/notify/page.dart:236 -msgid "避難資訊" -msgstr "避難資訊" +#: ./lib/app/settings/notify/page.dart:236 +msgid "防災資訊" +msgstr "防災資訊" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:176 +#: ./lib/app/settings/map/page.dart:49 msgid "海嘯資訊" msgstr "海嘯資訊" -#: lib/route/announcement/announcement.dart:82 +#: ./lib/route/announcement/announcement.dart:82 msgid "公告" msgstr "公告" -#: lib/app/settings/page.dart:112 +#: ./lib/app/settings/page.dart:112 msgid "贊助我們" msgstr "贊助我們" -#: lib/route/image_viewer/image_viewer.dart:70 +#: ./lib/route/image_viewer/image_viewer.dart:70 msgid "設定" msgstr "設定" -#: lib/app/settings/notify/page.dart:60 +#: ./lib/app/settings/notify/page.dart:61 msgid "接收全部" msgstr "接收全部" -#: lib/app/settings/notify/page.dart:59 +#: ./lib/app/settings/notify/page.dart:60 msgid "關閉" msgstr "關閉" -#: lib/app/settings/notify/_widgets/eew_notify_section.dart:37 +#: ./lib/app/settings/notify/_widgets/eew_notify_section.dart:37 msgid "接收類別" msgstr "接收類別" -#: lib/app/settings/notify/page.dart:44 +#: ./lib/app/settings/notify/page.dart:45 msgid "所在地震度1以上" msgstr "所在地震度1以上" -#: lib/app/settings/notify/page.dart:55 +#: ./lib/app/settings/notify/page.dart:56 msgid "海嘯消息、海嘯警報" msgstr "海嘯消息、海嘯警報" -#: lib/app/settings/notify/page.dart:54 +#: ./lib/app/settings/notify/page.dart:55 msgid "只接收海嘯警報" msgstr "只接收海嘯警報" -#: lib/app/settings/notify/page.dart:50 +#: ./lib/app/settings/notify/page.dart:51 msgid "接收所在地" msgstr "接收所在地" -#: lib/app/settings/notify/page.dart:37 +#: ./lib/app/settings/notify/page.dart:38 msgid "所在地震度4以上" msgstr "所在地震度4以上" -#: lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:31 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:31 msgid "音效測試" msgstr "音效測試" -#: lib/app/settings/notify/(5.basic)/announcement/page.dart:32 +#: ./lib/app/settings/notify/(5.basic)/announcement/page.dart:32 msgid "發送公告時" msgstr "發送公告時" -#: lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:42 -msgid "" -"音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音" -"效。此測試不會向伺服器發送任何請求" -msgstr "" -"音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音" -"效。此測試不會向伺服器發送任何請求" +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:47 +msgid "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" +msgstr "音效測試為在裝置上執行的本地通知,僅用於確認裝置在接收通知時是否能正常播放音效。此測試不會向伺服器發送任何請求" -#: lib/app/settings/notify/page.dart:135 +#: ./lib/app/settings/notify/page.dart:135 msgid "請先設定所在地來使用通知功能" msgstr "請先設定所在地來使用通知功能" -#: lib/app/settings/notify/page.dart:142 +#: ./lib/app/settings/notify/page.dart:142 msgid "地震速報" msgstr "地震速報" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:160 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:128 msgid "地震" msgstr "地震" -#: lib/app/settings/notify/page.dart:204 +#: ./lib/app/settings/notify/page.dart:204 msgid "天氣" msgstr "天氣" -#: lib/app/settings/notify/page.dart:248 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:144 msgid "海嘯" msgstr "海嘯" -#: lib/app/settings/notify/page.dart:266 +#: ./lib/app/settings/notify/page.dart:266 msgid "其他" msgstr "其他" -#: lib/app/settings/notify/(3.weather)/advisory/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 msgid "重大" msgstr "重大" -#: lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 -msgid "" -"海嘯警報發布時\n" -"沿海地區鄉鎮" -msgstr "" -"海嘯警報發布時\n" -"沿海地區鄉鎮" +#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:33 +msgid "海嘯警報發布時" +msgstr "海嘯警報發布時" -#: lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:34 +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:39 msgid "一般" msgstr "一般" -#: lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 -msgid "" -"海嘯警報發布時\n" -"上述除外地區" -msgstr "" -"海嘯警報發布時\n" -"上述除外地區" +#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:34 +msgid "海嘯消息發布時" +msgstr "海嘯消息發布時" -#: lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 +#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息(無聲通知)" msgstr "太平洋海嘯消息(無聲通知)" -#: lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 +#: ./lib/app/settings/notify/(4.tsunami)/tsunami/page.dart:35 msgid "太平洋海嘯消息發布時" msgstr "太平洋海嘯消息發布時" -#: lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 +#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 msgid "強震監視器(一般)" msgstr "強震監視器(一般)" -#: lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 +#: ./lib/app/settings/notify/(2.earthquake)/monitor/page.dart:32 msgid "偵測到晃動" msgstr "偵測到晃動" -#: lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 +#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 msgid "震度速報(一般)" msgstr "震度速報(一般)" -#: lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 +#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:33 msgid "所在地(鄉鎮)實測震度 3 以上" msgstr "所在地(鄉鎮)實測震度 3 以上" -#: lib/app/settings/notify/(2.earthquake)/intensity/page.dart:35 +#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:35 msgid "震度速報(無聲通知)" msgstr "震度速報(無聲通知)" -#: lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36 +#: ./lib/app/settings/notify/(2.earthquake)/intensity/page.dart:36 msgid "所在地(鄉鎮)實測震度 1 以上" msgstr "所在地(鄉鎮)實測震度 1 以上" -#: lib/app/settings/notify/(2.earthquake)/report/page.dart:33 +#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:33 msgid "地震報告(一般)" msgstr "地震報告(一般)" -#: lib/app/settings/notify/(2.earthquake)/report/page.dart:33 +#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:33 msgid "所在地(縣市)實測震度 3 以上" msgstr "所在地(縣市)實測震度 3 以上" -#: lib/app/settings/notify/(2.earthquake)/report/page.dart:34 +#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:34 msgid "地震報告(無聲通知)" msgstr "地震報告(無聲通知)" -#: lib/app/settings/notify/(2.earthquake)/report/page.dart:34 +#: ./lib/app/settings/notify/(2.earthquake)/report/page.dart:34 msgid "所在地(縣市)實測震度 1 以上" msgstr "所在地(縣市)實測震度 1 以上" -#: lib/app/settings/notify/_lib/utils.dart:13 +#: ./lib/app/settings/notify/_lib/utils.dart:13 msgid "已更新通知設定" msgstr "已更新通知設定" -#: lib/app/settings/notify/_lib/utils.dart:17 +#: ./lib/app/settings/notify/_lib/utils.dart:17 msgid "更新通知設定失敗" msgstr "更新通知設定失敗" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:34 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:34 msgid "緊急地震速報(重大)" msgstr "緊急地震速報(重大)" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:35 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:35 msgid "" "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 4 以上" @@ -244,11 +235,11 @@ msgstr "" "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 4 以上" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:39 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:39 msgid "緊急地震速報(一般)" msgstr "緊急地震速報(一般)" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:40 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:40 msgid "" "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 2 以上" @@ -256,11 +247,11 @@ msgstr "" "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 2 以上" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:44 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:44 msgid "緊急地震速報(無聲)" msgstr "緊急地震速報(無聲)" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:45 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:45 msgid "" "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 1 以上" @@ -268,39 +259,39 @@ msgstr "" "最大震度 5 弱以上 且\n" "所在地(鄉鎮)預估震度 1 以上" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:48 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:48 msgid "地震速報(重大)" msgstr "地震速報(重大)" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:48 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:48 msgid "所在地(鄉鎮)預估震度 4 以上" msgstr "所在地(鄉鎮)預估震度 4 以上" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:49 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:49 msgid "地震速報(一般)" msgstr "地震速報(一般)" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:49 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:49 msgid "所在地(鄉鎮)預估震度 2 以上" msgstr "所在地(鄉鎮)預估震度 2 以上" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:50 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:50 msgid "地震速報(無聲)" msgstr "地震速報(無聲)" -#: lib/app/settings/notify/(1.eew)/eew/page.dart:50 +#: ./lib/app/settings/notify/(1.eew)/eew/page.dart:50 msgid "所在地(鄉鎮)預估震度 1 以上" msgstr "所在地(鄉鎮)預估震度 1 以上" -#: lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 -msgid "所在地(鄉鎮)發布避難警訊時" -msgstr "所在地(鄉鎮)發布避難警訊時" +#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:33 +msgid "所在地(鄉鎮)發布防災警訊時" +msgstr "所在地(鄉鎮)發布防災警訊時" -#: lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 -msgid "所在地(鄉鎮)發布避難資訊時" -msgstr "所在地(鄉鎮)發布避難資訊時" +#: ./lib/app/settings/notify/(3.weather)/evacuation/page.dart:34 +msgid "所在地(鄉鎮)發布防災資訊時" +msgstr "所在地(鄉鎮)發布防災資訊時" -#: lib/app/settings/notify/(3.weather)/advisory/page.dart:35 +#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:35 msgid "" "所在地(鄉鎮)發布紅色燈號之\n" "天氣警特報" @@ -308,7 +299,7 @@ msgstr "" "所在地(鄉鎮)發布紅色燈號之\n" "天氣警特報" -#: lib/app/settings/notify/(3.weather)/advisory/page.dart:40 +#: ./lib/app/settings/notify/(3.weather)/advisory/page.dart:40 msgid "" "所在地(鄉鎮)發布上述除外燈號之\n" "天氣警特報" @@ -316,316 +307,419 @@ msgstr "" "所在地(鄉鎮)發布上述除外燈號之\n" "天氣警特報" -#: lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 -msgid "" -"所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" -msgstr "" -"所在地(鄉鎮)發布雷雨即時訊息或\n" -"山區暴雨時" +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:35 +msgid "所在地(鄉鎮)發布山區暴雨時" +msgstr "所在地(鄉鎮)發布山區暴雨時" + +#: ./lib/app/settings/notify/(3.weather)/thunderstorm/page.dart:40 +msgid "所在地(鄉鎮)發布雷雨即時訊息時" +msgstr "所在地(鄉鎮)發布雷雨即時訊息時" -#: lib/app/settings/unit/page.dart:28 +#: ./lib/app/settings/unit/page.dart:28 msgid "使用華氏度" msgstr "使用華氏度" -#: lib/app/settings/unit/page.dart:29 +#: ./lib/app/settings/unit/page.dart:29 msgid "切換溫度顯示單位為華氏度 (℉)" msgstr "切換溫度顯示單位為華氏度 (℉)" -#: lib/app/settings/locale/page.dart:31 +#: ./lib/app/settings/locale/page.dart:31 msgid "顯示語言" msgstr "顯示語言" -#: lib/app/settings/locale/page.dart:32 +#: ./lib/app/settings/locale/page.dart:32 msgid "系統語言" msgstr "系統語言" -#: lib/app/settings/locale/page.dart:40 +#: ./lib/app/settings/locale/page.dart:40 msgid "協助翻譯" msgstr "協助翻譯" -#: lib/app/settings/locale/page.dart:41 +#: ./lib/app/settings/locale/page.dart:41 msgid "點擊這裡來幫助我們改進 DPIP 的翻譯" msgstr "點擊這裡來幫助我們改進 DPIP 的翻譯" -#: lib/app/settings/locale/select/page.dart:46 +#: ./lib/app/settings/locale/select/page.dart:46 msgid "選擇語言" msgstr "選擇語言" -#: lib/app/settings/locale/select/page.dart:67 +#: ./lib/app/settings/locale/select/page.dart:67 msgid "已翻譯 {translated}・已校對 {approved}" msgstr "已翻譯 {translated}・已校對 {approved}" -#: lib/app/settings/locale/select/page.dart:95 +#: ./lib/app/settings/locale/select/page.dart:95 msgid "來源語言" msgstr "來源語言" -#: lib/app/settings/donate/page.dart:38 +#: ./lib/app/settings/donate/page.dart:46 msgid "無法連線至商店,請稍後再試" msgstr "無法連線至商店,請稍後再試" -#: lib/app/settings/donate/page.dart:44 +#: ./lib/app/settings/donate/page.dart:52 msgid "找不到商品,請稍候再試" msgstr "找不到商品,請稍候再試" -#: lib/app/settings/donate/page.dart:105 +#: ./lib/app/settings/donate/page.dart:134 msgid "重新載入" msgstr "重新載入" -#: lib/app/settings/donate/page.dart:115 +#: ./lib/app/settings/donate/page.dart:144 msgid "正在載入商店物品中" msgstr "正在載入商店物品中" -#: lib/app/settings/donate/page.dart:132 +#: ./lib/app/settings/donate/page.dart:161 msgid "" -"DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維" -"持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與" -"維護的成本。\n" +"DPIP 作為一款致力於提供即時地震資訊的 " +"App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n" "\n" -"您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地" -"為您提供服務。感謝您的理解與慷慨!" +"您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" msgstr "" -"DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維" -"持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與" -"維護的成本。\n" +"DPIP 作為一款致力於提供即時地震資訊的 " +"App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n" "\n" -"您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地" -"為您提供服務。感謝您的理解與慷慨!" +"您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!" -#: lib/app/settings/donate/page.dart:141 +#: ./lib/app/settings/donate/page.dart:169 msgid "訂閱制" msgstr "訂閱制" -#: lib/app/settings/donate/page.dart:150 +#: ./lib/app/settings/donate/page.dart:196 msgid "{price}/月" msgstr "{price}/月" -#: lib/app/settings/donate/page.dart:162 +#: ./lib/app/settings/donate/page.dart:220 msgid "單次支援" msgstr "單次支援" -#: lib/app/settings/donate/page.dart:197 -#, fuzzy +#: ./lib/app/settings/donate/page.dart:284 msgid "無法連線至 {store},請稍後再試。" msgstr "無法連線至 {store},請稍後再試。" -#: lib/app/settings/donate/page.dart:202 +#: ./lib/app/settings/donate/page.dart:290 msgid "正在恢復您購買的訂閱" msgstr "正在恢復您購買的訂閱" -#: lib/app/settings/donate/page.dart:205 +#: ./lib/app/settings/donate/page.dart:292 msgid "恢復購買" msgstr "恢復購買" -#: lib/app/settings/donate/page.dart:216 +#: ./lib/app/settings/donate/page.dart:299 msgid "使用條款" msgstr "使用條款" -#: lib/app/settings/donate/page.dart:223 +#: ./lib/app/settings/donate/page.dart:306 msgid "隱私權政策" msgstr "隱私權政策" -#: lib/app/welcome/4-permissions/page.dart:163 +#: ./lib/app/welcome/4-permissions/page.dart:161 msgid "位置" msgstr "位置" -#: lib/app/settings/page.dart:39 +#: ./lib/app/settings/page.dart:39 msgid "設定你的所在地來接收當地的即時資訊" msgstr "設定你的所在地來接收當地的即時資訊" -#: lib/app/settings/page.dart:48 +#: ./lib/app/settings/page.dart:48 msgid "介面" msgstr "介面" -#: lib/app/settings/page.dart:53 +#: ./lib/app/settings/page.dart:53 msgid "調整 DPIP 整體的外觀與顏色" msgstr "調整 DPIP 整體的外觀與顏色" -#: lib/app/settings/page.dart:61 +#: ./lib/app/settings/page.dart:61 msgid "調整 DPIP 的顯示語言" msgstr "調整 DPIP 的顯示語言" -#: lib/app/settings/page.dart:69 +#: ./lib/app/settings/page.dart:69 msgid "調整 DPIP 顯示數值時使用的單位" msgstr "調整 DPIP 顯示數值時使用的單位" -#: lib/app/settings/page.dart:75 +#: ./lib/app/settings/page.dart:75 msgid "調整 DPIP 地圖的設定" msgstr "調整 DPIP 地圖的設定" -#: lib/app/settings/page.dart:87 +#: ./lib/app/settings/page.dart:87 msgid "推播通知設定與通知音效測試" msgstr "推播通知設定與通知音效測試" -#: lib/app/settings/page.dart:94 +#: ./lib/app/settings/page.dart:94 msgid "資訊" msgstr "資訊" -#: lib/app/settings/page.dart:99 +#: ./lib/app/settings/page.dart:99 msgid "掌握 ExpTech Studio 的最新公告與資訊" msgstr "掌握 ExpTech Studio 的最新公告與資訊" -#: lib/app/changelog/page.dart:54 +#: ./lib/app/changelog/page.dart:54 msgid "更新日誌" msgstr "更新日誌" -#: lib/app/settings/page.dart:106 +#: ./lib/app/settings/page.dart:106 msgid "瀏覽 DPIP 的歷次更新紀錄" msgstr "瀏覽 DPIP 的歷次更新紀錄" -#: lib/app/settings/page.dart:113 +#: ./lib/app/settings/page.dart:113 msgid "幫助我們維護伺服器的穩定和長久發展" msgstr "幫助我們維護伺服器的穩定和長久發展" -#: lib/app/settings/page.dart:119 +#: ./lib/app/settings/page.dart:119 msgid "第三方套件授權" msgstr "第三方套件授權" -#: lib/app/settings/page.dart:120 +#: ./lib/app/settings/page.dart:120 msgid "DPIP 的實現歸功於開放源始碼" msgstr "DPIP 的實現歸功於開放源始碼" -#: lib/app/settings/page.dart:162 +#: ./lib/app/settings/page.dart:162 msgid "除錯" msgstr "除錯" -#: lib/app/settings/page.dart:166 +#: ./lib/app/settings/page.dart:166 msgid "應用程式版本" msgstr "應用程式版本" -#: lib/app/settings/page.dart:172 +#: ./lib/app/settings/page.dart:172 msgid "裝置資訊" msgstr "裝置資訊" -#: lib/app/settings/page.dart:178 +#: ./lib/app/settings/page.dart:178 msgid "複製通知 Token" msgstr "複製通知 Token" -#: lib/app/debug/logs/page.dart:16 +#: ./lib/app/debug/logs/page.dart:16 msgid "App 日誌" msgstr "App 日誌" -#: lib/app/welcome/3-notice/page.dart:58 +#: ./lib/app/welcome/3-notice/page.dart:58 msgid "任何資訊應以中央氣象署發布之內容為準。" msgstr "任何資訊應以中央氣象署發布之內容為準。" -#: lib/app/settings/location/page.dart:422 +#: ./lib/app/settings/location/page.dart:76 +msgid "無法取得通知權限" +msgstr "無法取得通知權限" + +#: ./lib/app/settings/location/page.dart:78 +msgid "無法取得位置權限" +msgstr "無法取得位置權限" + +#: ./lib/app/settings/location/page.dart:79 +msgid "無法取得自啟動權限" +msgstr "無法取得自啟動權限" + +#: ./lib/app/welcome/4-permissions/page.dart:167 +msgid "省電策略" +msgstr "省電策略" + +#: ./lib/route/image_viewer/image_viewer.dart:57 +msgid "無法取得權限" +msgstr "無法取得權限" + +#: ./lib/app/settings/location/page.dart:85 +msgid "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" +msgstr "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。" + +#: ./lib/app/settings/location/page.dart:86 +msgid "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" +msgstr "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。" + +#: ./lib/app/settings/location/page.dart:89 +msgid "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" +msgstr "自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。" + +#: ./lib/app/settings/location/page.dart:90 +msgid "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" +msgstr "自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。" + +#: ./lib/app/settings/location/page.dart:91 +msgid "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" + +#: ./lib/app/settings/location/page.dart:92 +msgid "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" +msgstr "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" + +#: ./lib/app/settings/location/page.dart:93 +msgid "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" +msgstr "自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。" + +#: ./lib/route/image_viewer/image_viewer.dart:64 +msgid "取消" +msgstr "取消" + +#: ./lib/app/settings/location/page.dart:163 +msgid "自動啟動" +msgstr "自動啟動" + +#: ./lib/app/settings/location/page.dart:164 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" + +#: ./lib/app/settings/location/page.dart:186 +msgid "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" +msgstr "為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。" + +#: ./lib/app/settings/location/page.dart:220 +msgid "一律允許" +msgstr "一律允許" + +#: ./lib/app/settings/location/page.dart:220 +msgid "永遠" +msgstr "永遠" + +#: ./lib/app/settings/location/page.dart:231 msgid "自動更新" msgstr "自動更新" -#: lib/app/settings/location/page.dart:423 +#: ./lib/app/settings/location/page.dart:232 msgid "定期更新目前的所在地" msgstr "定期更新目前的所在地" -#: lib/app/settings/location/page.dart:433 +#: ./lib/app/settings/location/page.dart:242 msgid "" -"自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的" -"地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新" -"狀況。" +"自動定位功能將使用您的裝置上的 GPS,即使 DPIP " +"關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" msgstr "" -"自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的" -"地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新" -"狀況。" +"自動定位功能將使用您的裝置上的 GPS,即使 DPIP " +"關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。" -#: lib/app/settings/location/page.dart:564 -msgid "直轄市/縣市" -msgstr "直轄市/縣市" +#: ./lib/app/settings/location/page.dart:301 +msgid "通知功能已被拒絕,請移至設定允許權限。" +msgstr "通知功能已被拒絕,請移至設定允許權限。" -#: lib/app/home/_widgets/location_button.dart:21 -msgid "尚未設定" -msgstr "尚未設定" +#: ./lib/app/settings/location/page.dart:326 +msgid "自啟動權限已被拒絕,請移至設定允許權限。" +msgstr "自啟動權限已被拒絕,請移至設定允許權限。" -#: lib/app/settings/location/page.dart:592 -msgid "鄉鎮市區" -msgstr "鄉鎮市區" +#: ./lib/app/settings/location/page.dart:352 +msgid "省電策略已被拒絕,請移至設定允許權限。" +msgstr "省電策略已被拒絕,請移至設定允許權限。" -#: lib/app/settings/location/select/page.dart:26 +#: ./lib/app/settings/location/page.dart:413 +msgid "設定所在地時發生錯誤,請稍候再試一次。" +msgstr "設定所在地時發生錯誤,請稍候再試一次。" + +#: ./lib/app/settings/location/select/page.dart:38 msgid "縣市" msgstr "縣市" -#: lib/app/settings/location/select/page.dart:38 +#: ./lib/app/settings/location/select/page.dart:49 msgid "目前所在地" msgstr "目前所在地" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:138 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:134 +msgid "監視器" +msgstr "監視器" + +#: ./lib/app/map/_lib/managers/radar.dart:505 +msgid "雷達回波" +msgstr "雷達回波" + +#: ./lib/app/map/_lib/managers/temperature.dart:382 +msgid "氣溫" +msgstr "氣溫" + +#: ./lib/app/map/_lib/managers/precipitation.dart:470 +msgid "降水" +msgstr "降水" + +#: ./lib/app/map/_lib/managers/wind.dart:271 +msgid "風向/風速" +msgstr "風向/風速" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:112 +msgid "簡單" +msgstr "簡單" + +#: ./lib/app/settings/map/page.dart:57 +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#: ./lib/app/settings/map/page.dart:58 +msgid "Google" +msgstr "Google" + +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:106 msgid "底圖" msgstr "底圖" -#: lib/app/settings/map/page.dart:49 +#: ./lib/app/settings/map/page.dart:84 msgid "初始圖層" msgstr "初始圖層" -#: lib/app/settings/map/page.dart:71 +#: ./lib/app/settings/map/page.dart:107 msgid "動畫幀率" msgstr "動畫幀率" -#: lib/app/settings/map/page.dart:99 +#: ./lib/app/settings/map/page.dart:111 +msgid "影響強震監視器的震波模擬動畫流暢度" +msgstr "影響強震監視器的震波模擬動畫流暢度" + +#: ./lib/app/settings/map/page.dart:142 msgid "過高的動畫幀率可能會造成卡頓或設備發熱" msgstr "過高的動畫幀率可能會造成卡頓或設備發熱" -#: lib/app/settings/theme/page.dart:30 +#: ./lib/app/settings/theme/page.dart:30 msgid "主題模式" msgstr "主題模式" -#: lib/app/settings/theme/select/page.dart:57 +#: ./lib/app/settings/theme/select/page.dart:57 msgid "淺色" msgstr "淺色" -#: lib/app/settings/theme/select/page.dart:58 +#: ./lib/app/settings/theme/select/page.dart:58 msgid "深色" msgstr "深色" -#: lib/app/settings/theme/select/page.dart:55 +#: ./lib/app/settings/theme/select/page.dart:55 msgid "跟隨系統主題" msgstr "跟隨系統主題" -#: lib/app/settings/theme/select/page.dart:22 +#: ./lib/app/settings/theme/select/page.dart:22 msgid "主題色" msgstr "主題色" -#: lib/app/settings/theme/page.dart:46 +#: ./lib/app/settings/theme/page.dart:46 msgid "系統色彩" msgstr "系統色彩" -#: lib/app/settings/theme/page.dart:88 +#: ./lib/app/settings/theme/page.dart:88 msgid "使用系統顏色" msgstr "使用系統顏色" -#: lib/route/image_viewer/image_viewer.dart:64 -msgid "取消" -msgstr "取消" - -#: lib/route/image_viewer/image_viewer.dart:130 +#: ./lib/route/image_viewer/image_viewer.dart:130 msgid "確定" msgstr "確定" -#: lib/app/home/_widgets/thunderstorm_card.dart:76 -msgid "" -"您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。" -msgstr "" -"您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。" +#: ./lib/app/home/_widgets/thunderstorm_card.dart:76 +msgid "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。" +msgstr "您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。" -#: lib/app/home/_widgets/location_out_of_service.dart:24 +#: ./lib/app/home/_widgets/location_out_of_service.dart:24 msgid "服務區域外,僅在臺灣各地可用" msgstr "服務區域外,僅在臺灣各地可用" -#: lib/app/map/_lib/managers/radar.dart:499 -msgid "雷達回波" -msgstr "雷達回波" +#: ./lib/app/home/_widgets/location_button.dart:25 +msgid "尚未設定" +msgstr "尚未設定" -#: lib/app/home/_widgets/weather_header.dart:127 +#: ./lib/app/home/_widgets/weather_header.dart:127 msgid "體感約 {apparent}°" msgstr "體感約 {apparent}°" -#: lib/app/home/_widgets/location_not_set_card.dart:30 +#: ./lib/app/home/_widgets/location_not_set_card.dart:30 msgid "尚未設定所在地" msgstr "尚未設定所在地" -#: lib/app/map/_lib/managers/monitor.dart:874 +#: ./lib/app/map/_lib/managers/monitor.dart:1079 +msgid "EEW" +msgstr "EEW" + +#: ./lib/app/map/_lib/managers/monitor.dart:1089 msgid "第 {serial} 報" msgstr "第 {serial} 報" -#: lib/app/map/_lib/managers/monitor.dart:889 +#: ./lib/app/map/_lib/managers/monitor.dart:1103 msgid "" "{time} 左右,{location}附近發生有感地震,預估規模 " "M{magnitude}、所在地最大震度{intensity}。" @@ -633,656 +727,658 @@ msgstr "" "{time} 左右,{location}附近發生有感地震,預估規模 " "M{magnitude}、所在地最大震度{intensity}。" -#: lib/app/map/_lib/managers/monitor.dart:923 +#: ./lib/app/map/_lib/managers/monitor.dart:926 +msgid "" +"{time} 左右,{location}附近發生有感地震,預估規模 " +"M{magnitude}、深度{depth}公里。" +msgstr "" +"{time} 左右,{location}附近發生有感地震,預估規模 " +"M{magnitude}、深度{depth}公里。" + +#: ./lib/app/map/_lib/managers/monitor.dart:1137 msgid "所在地預估" msgstr "所在地預估" -#: lib/app/map/_lib/managers/monitor.dart:957 +#: ./lib/app/map/_lib/managers/monitor.dart:1171 msgid "震波" msgstr "震波" -#: lib/app/map/_lib/managers/monitor.dart:978 +#: ./lib/app/map/_lib/managers/monitor.dart:1191 msgid " 秒" msgstr " 秒" -#: lib/app/map/_lib/managers/monitor.dart:994 +#: ./lib/app/map/_lib/managers/monitor.dart:1207 msgid "抵達" msgstr "抵達" -#: lib/app/home/page.dart:55 +#: ./lib/app/home/page.dart:56 msgid "已更新至 {version}" msgstr "已更新至 {version}" -#: lib/utils/weather_icon.dart:282 +#: ./lib/utils/weather_icon.dart:282 msgid "取得天氣異常" msgstr "取得天氣異常" -#: lib/app/changelog/page.dart:109 +#: ./lib/app/changelog/page.dart:109 msgid "無法載入更新日誌,請稍後再試。" msgstr "無法載入更新日誌,請稍後再試。" -#: lib/app/changelog/page.dart:113 +#: ./lib/app/changelog/page.dart:113 msgid "重試" msgstr "重試" -#: lib/app/welcome/4-permissions/page.dart:366 +#: ./lib/app/welcome/4-permissions/page.dart:364 msgid "下一步" msgstr "下一步" -#: lib/app/welcome/1-about/page.dart:60 +#: ./lib/app/welcome/1-about/page.dart:60 msgid "防災資訊平台" msgstr "防災資訊平台" -#: lib/app/welcome/2-exptech/page.dart:83 +#: ./lib/app/welcome/2-exptech/page.dart:83 msgid "我們是誰?" msgstr "我們是誰?" -#: lib/app/welcome/2-exptech/page.dart:88 -msgid "" -"ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團" -"體。成員來自臺灣北中南、日本、韓國、中國的學生。" -msgstr "" -"ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團" -"體。成員來自臺灣北中南、日本、韓國、中國的學生。" +#: ./lib/app/welcome/2-exptech/page.dart:88 +msgid "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" +msgstr "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" -#: lib/app/welcome/2-exptech/page.dart:93 +#: ./lib/app/welcome/2-exptech/page.dart:93 msgid "我們的初衷" msgstr "我們的初衷" -#: lib/app/welcome/2-exptech/page.dart:98 -msgid "" -"成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成" -"現在的樣子。" -msgstr "" -"成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成" -"現在的樣子。" +#: ./lib/app/welcome/2-exptech/page.dart:98 +msgid "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" +msgstr "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" -#: lib/app/welcome/3-notice/page.dart:38 +#: ./lib/app/welcome/3-notice/page.dart:38 msgid "注意事項" msgstr "注意事項" -#: lib/app/welcome/3-notice/page.dart:75 -msgid "" -"根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可" -"能性,我們會盡力避免此類情況,但不保證一定不會發生。" -msgstr "" -"根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可" -"能性,我們會盡力避免此類情況,但不保證一定不會發生。" +#: ./lib/app/welcome/3-notice/page.dart:75 +msgid "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" +msgstr "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" -#: lib/app/welcome/3-notice/page.dart:88 +#: ./lib/app/welcome/3-notice/page.dart:88 msgid "強烈搖晃有機率比通知早抵達使用者所在地。" msgstr "強烈搖晃有機率比通知早抵達使用者所在地。" -#: lib/app/welcome/3-notice/page.dart:99 +#: ./lib/app/welcome/3-notice/page.dart:99 msgid "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" msgstr "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" -#: lib/app/welcome/3-notice/page.dart:110 +#: ./lib/app/welcome/3-notice/page.dart:110 msgid "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" msgstr "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" -#: lib/app/welcome/1-about/page.dart:40 +#: ./lib/app/welcome/1-about/page.dart:40 msgid "歡迎使用 DPIP" msgstr "歡迎使用 DPIP" -#: lib/app/welcome/1-about/page.dart:81 +#: ./lib/app/welcome/1-about/page.dart:81 msgid "" -"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資" -"訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" +"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) " +"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" msgstr "" -"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資" -"訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" +"DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) " +"之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" -#: lib/app/welcome/4-permissions/page.dart:156 +#: ./lib/app/welcome/4-permissions/page.dart:154 msgid "在重大災害發生時以通知來傳遞即時防災資訊" msgstr "在重大災害發生時以通知來傳遞即時防災資訊" -#: lib/app/welcome/4-permissions/page.dart:164 +#: ./lib/app/welcome/4-permissions/page.dart:162 msgid "使用定位來自動更新所在地設定,提供當地的即時防災資訊" msgstr "使用定位來自動更新所在地設定,提供當地的即時防災資訊" -#: lib/app/welcome/4-permissions/page.dart:169 -msgid "省電策略" -msgstr "省電策略" - -#: lib/app/welcome/4-permissions/page.dart:170 +#: ./lib/app/welcome/4-permissions/page.dart:168 msgid "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" msgstr "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。" -#: lib/route/image_viewer/image_viewer.dart:228 +#: ./lib/route/image_viewer/image_viewer.dart:228 msgid "儲存" msgstr "儲存" -#: lib/app/welcome/4-permissions/page.dart:177 +#: ./lib/app/welcome/4-permissions/page.dart:175 msgid "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" msgstr "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" -#: lib/app/welcome/4-permissions/page.dart:344 +#: ./lib/app/welcome/4-permissions/page.dart:342 msgid "權限請求" msgstr "權限請求" -#: lib/app/welcome/4-permissions/page.dart:345 +#: ./lib/app/welcome/4-permissions/page.dart:343 msgid "需要使用者手動到設定開啟相關權限。" msgstr "需要使用者手動到設定開啟相關權限。" -#: lib/app/welcome/4-permissions/page.dart:385 +#: ./lib/app/welcome/4-permissions/page.dart:383 msgid "權限" msgstr "權限" -#: lib/app/welcome/4-permissions/page.dart:398 +#: ./lib/app/welcome/4-permissions/page.dart:396 msgid "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" msgstr "我們一直和使用者站在一起,為使用者的隱私而不斷努力。" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:131 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:99 msgid "地圖圖層" msgstr "地圖圖層" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:132 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:100 msgid "選擇要顯示的地圖圖層" msgstr "選擇要顯示的地圖圖層" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:144 -msgid "線條" -msgstr "線條" +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:139 +msgid "報告" +msgstr "報告" -#: lib/app/map/_widgets/layer_toggle_sheet.dart:182 +#: ./lib/app/map/_widgets/layer_toggle_sheet.dart:150 msgid "氣象" msgstr "氣象" -#: lib/app/map/_lib/managers/temperature.dart:332 -msgid "氣溫" -msgstr "氣溫" - -#: lib/app/map/_lib/managers/precipitation.dart:445 -msgid "降水" -msgstr "降水" - -#: lib/app/map/_lib/managers/wind.dart:223 -msgid "風向/風速" -msgstr "風向/風速" +#: ./lib/app/map/_widgets/map_legend.dart:181 +msgid "單位:{unit}" +msgstr "單位:{unit}" -#: lib/app/map/_lib/managers/radar.dart:613 +#: ./lib/app/map/_lib/managers/radar.dart:619 msgid "長按設定播放起點" msgstr "長按設定播放起點" -#: lib/app/map/_lib/managers/radar.dart:627 +#: ./lib/app/map/_lib/managers/radar.dart:633 msgid "目前時間" msgstr "目前時間" -#: lib/app/map/_lib/managers/radar.dart:632 -#, fuzzy +#: ./lib/app/map/_lib/managers/radar.dart:638 msgid "播放起點" msgstr "播放起點" -#: lib/app/map/_lib/managers/radar.dart:906 +#: ./lib/app/map/_lib/managers/radar.dart:938 msgid "播放進度" msgstr "播放進度" -#: lib/app/map/_lib/managers/precipitation.dart:305 +#: ./lib/app/map/_lib/managers/precipitation.dart:328 msgid "今日" msgstr "今日" -#: lib/app/map/_lib/managers/precipitation.dart:306 +#: ./lib/app/map/_lib/managers/precipitation.dart:329 msgid "10 分鐘" msgstr "10 分鐘" -#: lib/app/map/_lib/managers/precipitation.dart:307 +#: ./lib/app/map/_lib/managers/precipitation.dart:330 msgid "1 小時" msgstr "1 小時" -#: lib/app/map/_lib/managers/precipitation.dart:308 +#: ./lib/app/map/_lib/managers/precipitation.dart:331 msgid "3 小時" msgstr "3 小時" -#: lib/app/map/_lib/managers/precipitation.dart:309 +#: ./lib/app/map/_lib/managers/precipitation.dart:332 msgid "6 小時" msgstr "6 小時" -#: lib/app/map/_lib/managers/precipitation.dart:310 +#: ./lib/app/map/_lib/managers/precipitation.dart:333 msgid "12 小時" msgstr "12 小時" -#: lib/app/map/_lib/managers/precipitation.dart:311 +#: ./lib/app/map/_lib/managers/precipitation.dart:334 msgid "24 小時" msgstr "24 小時" -#: lib/app/map/_lib/managers/precipitation.dart:312 +#: ./lib/app/map/_lib/managers/precipitation.dart:335 msgid "2 天" msgstr "2 天" -#: lib/app/map/_lib/managers/precipitation.dart:313 +#: ./lib/app/map/_lib/managers/precipitation.dart:336 msgid "3 天" msgstr "3 天" -#: lib/app/map/_lib/managers/monitor.dart:714 +#: ./lib/app/map/_lib/managers/monitor.dart:239 +msgid "海外測站" +msgstr "海外測站" + +#: ./lib/app/map/_lib/managers/monitor.dart:261 +msgid "即時震度:" +msgstr "即時震度:" + +#: ./lib/app/map/_lib/managers/monitor.dart:267 +msgid "地動加速度:" +msgstr "地動加速度:" + +#: ./lib/app/map/_lib/managers/monitor.dart:274 +msgid "地動速度:" +msgstr "地動速度:" + +#: ./lib/app/map/_lib/managers/monitor.dart:279 +msgid "無資料" +msgstr "無資料" + +#: ./lib/app/map/_lib/managers/monitor.dart:792 msgid "目前沒有生效中的地震速報" msgstr "目前沒有生效中的地震速報" -#: lib/app/map/_lib/managers/monitor.dart:808 +#: ./lib/app/map/_lib/managers/monitor.dart:865 +msgid "規模 M{magnitude},深度{depth}公里" +msgstr "規模 M{magnitude},深度{depth}公里" + +#: ./lib/app/map/_lib/managers/monitor.dart:1030 msgid "規模 M{magnitude},所在地預估{intensity}" msgstr "規模 M{magnitude},所在地預估{intensity}" -#: lib/app/map/_lib/managers/monitor.dart:824 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "{countdown}秒後抵達" msgstr "{countdown}秒後抵達" -#: lib/app/map/_lib/managers/monitor.dart:825 +#: ./lib/app/map/_lib/managers/monitor.dart:1039 msgid "已抵達" msgstr "已抵達" -#: lib/app/map/_lib/managers/report.dart:371 +#: ./lib/app/map/_lib/managers/report.dart:369 msgid "近期的地震報告" msgstr "近期的地震報告" -#: lib/app/map/_lib/managers/report.dart:376 +#: ./lib/app/map/_lib/managers/report.dart:374 msgid "更多" msgstr "更多" -#: lib/app/map/_lib/managers/report.dart:592 +#: ./lib/app/map/_lib/managers/report.dart:599 msgid "編號 {number} 顯著有感地震" msgstr "編號 {number} 顯著有感地震" -#: lib/app/map/_lib/managers/report.dart:593 +#: ./lib/app/map/_lib/managers/report.dart:600 msgid "小區域有感地震" msgstr "小區域有感地震" -#: lib/app/map/_lib/managers/report.dart:652 +#: ./lib/app/map/_lib/managers/report.dart:656 msgid "地震規模" msgstr "地震規模" -#: lib/app/map/_lib/managers/report.dart:674 +#: ./lib/app/map/_lib/managers/report.dart:678 msgid "震源深度" msgstr "震源深度" -#: lib/app/map/_lib/managers/report.dart:611 +#: ./lib/app/map/_lib/managers/report.dart:615 msgid "報告頁面" msgstr "報告頁面" -#: lib/app/map/_lib/managers/report.dart:635 +#: ./lib/app/map/_lib/managers/report.dart:639 msgid "發震時間" msgstr "發震時間" -#: lib/app/map/_lib/managers/report.dart:642 +#: ./lib/app/map/_lib/managers/report.dart:646 msgid "位於" msgstr "位於" -#: lib/app/map/_lib/managers/report.dart:698 +#: ./lib/app/map/_lib/managers/report.dart:702 msgid "各地震度" msgstr "各地震度" -#: lib/app/map/_lib/managers/report.dart:769 +#: ./lib/app/map/_lib/managers/report.dart:773 msgid "地震報告圖" msgstr "地震報告圖" -#: lib/app/map/_lib/managers/report.dart:779 +#: ./lib/app/map/_lib/managers/report.dart:783 msgid "震度圖" msgstr "震度圖" -#: lib/app/map/_lib/managers/report.dart:789 +#: ./lib/app/map/_lib/managers/report.dart:793 msgid "最大地動加速度圖" msgstr "最大地動加速度圖" -#: lib/app/map/_lib/managers/report.dart:799 +#: ./lib/app/map/_lib/managers/report.dart:803 msgid "最大地動速度圖" msgstr "最大地動速度圖" -#: lib/route/announcement/announcement.dart:12 +#: ./lib/route/announcement/announcement.dart:12 msgid "錯誤" msgstr "錯誤" -#: lib/route/announcement/announcement.dart:13 +#: ./lib/route/announcement/announcement.dart:13 msgid "已解決" msgstr "已解決" -#: lib/route/announcement/announcement.dart:14 +#: ./lib/route/announcement/announcement.dart:14 msgid "影響:小" msgstr "影響:小" -#: lib/route/announcement/announcement.dart:15 +#: ./lib/route/announcement/announcement.dart:15 msgid "影響:中" msgstr "影響:中" -#: lib/route/announcement/announcement.dart:16 +#: ./lib/route/announcement/announcement.dart:16 msgid "影響:大" msgstr "影響:大" -#: lib/route/announcement/announcement.dart:18 +#: ./lib/route/announcement/announcement.dart:18 msgid "維修" msgstr "維修" -#: lib/route/announcement/announcement.dart:19 -#, fuzzy +#: ./lib/route/announcement/announcement.dart:19 msgid "測試" msgstr "測試" -#: lib/route/announcement/announcement.dart:20 +#: ./lib/route/announcement/announcement.dart:20 msgid "變更" msgstr "變更" -#: lib/route/announcement/announcement.dart:21 +#: ./lib/route/announcement/announcement.dart:21 msgid "完成" msgstr "完成" -#: lib/route/announcement/announcement.dart:22 +#: ./lib/route/announcement/announcement.dart:22 msgid "地震相關" msgstr "地震相關" -#: lib/route/announcement/announcement.dart:23 +#: ./lib/route/announcement/announcement.dart:23 msgid "氣象相關" msgstr "氣象相關" -#: lib/route/announcement/announcement.dart:29 +#: ./lib/route/announcement/announcement.dart:29 msgid "未知" msgstr "未知" -#: lib/route/announcement/announcement.dart:103 +#: ./lib/route/announcement/announcement.dart:103 msgid "目前沒有公告" msgstr "目前沒有公告" -#: lib/route/announcement/announcement.dart:223 +#: ./lib/route/announcement/announcement.dart:223 msgid "公告詳情" msgstr "公告詳情" -#: lib/route/image_viewer/image_viewer.dart:57 -msgid "無法取得權限" -msgstr "無法取得權限" - -#: lib/route/image_viewer/image_viewer.dart:59 +#: ./lib/route/image_viewer/image_viewer.dart:59 msgid "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" msgstr "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" -#: lib/route/image_viewer/image_viewer.dart:70 +#: ./lib/route/image_viewer/image_viewer.dart:70 msgid "再試一次" msgstr "再試一次" -#: lib/route/image_viewer/image_viewer.dart:110 +#: ./lib/route/image_viewer/image_viewer.dart:110 msgid "已儲存圖片" msgstr "已儲存圖片" -#: lib/route/image_viewer/image_viewer.dart:126 +#: ./lib/route/image_viewer/image_viewer.dart:126 msgid "儲存圖片時發生錯誤" msgstr "儲存圖片時發生錯誤" -#: lib/utils/extensions/int.dart:13 +#: ./lib/utils/extensions/int.dart:13 msgid "0級" msgstr "0級" -#: lib/utils/extensions/int.dart:14 +#: ./lib/utils/extensions/int.dart:14 msgid "1級" msgstr "1級" -#: lib/utils/extensions/int.dart:15 +#: ./lib/utils/extensions/int.dart:15 msgid "2級" msgstr "2級" -#: lib/utils/extensions/int.dart:16 +#: ./lib/utils/extensions/int.dart:16 msgid "3級" msgstr "3級" -#: lib/utils/extensions/int.dart:17 +#: ./lib/utils/extensions/int.dart:17 msgid "4級" msgstr "4級" -#: lib/utils/extensions/int.dart:18 +#: ./lib/utils/extensions/int.dart:18 msgid "5弱" msgstr "5弱" -#: lib/utils/extensions/int.dart:19 +#: ./lib/utils/extensions/int.dart:19 msgid "5強" msgstr "5強" -#: lib/utils/extensions/int.dart:20 +#: ./lib/utils/extensions/int.dart:20 msgid "6弱" msgstr "6弱" -#: lib/utils/extensions/int.dart:21 +#: ./lib/utils/extensions/int.dart:21 msgid "6強" msgstr "6強" -#: lib/utils/extensions/int.dart:22 +#: ./lib/utils/extensions/int.dart:22 msgid "7級" msgstr "7級" -#: lib/utils/weather_icon.dart:283 +#: ./lib/utils/weather_icon.dart:283 msgid "晴" msgstr "晴" -#: lib/utils/weather_icon.dart:284 +#: ./lib/utils/weather_icon.dart:284 msgid "晴有霾" msgstr "晴有霾" -#: lib/utils/weather_icon.dart:285 +#: ./lib/utils/weather_icon.dart:285 msgid "晴有靄" msgstr "晴有靄" -#: lib/utils/weather_icon.dart:286 +#: ./lib/utils/weather_icon.dart:286 msgid "晴有閃電" msgstr "晴有閃電" -#: lib/utils/weather_icon.dart:302 +#: ./lib/utils/weather_icon.dart:302 msgid "晴天伴有雷" msgstr "晴天伴有雷" -#: lib/utils/weather_icon.dart:288 +#: ./lib/utils/weather_icon.dart:288 msgid "晴有霧" msgstr "晴有霧" -#: lib/utils/weather_icon.dart:289 +#: ./lib/utils/weather_icon.dart:289 msgid "晴有雨" msgstr "晴有雨" -#: lib/utils/weather_icon.dart:290 +#: ./lib/utils/weather_icon.dart:290 msgid "晴有雨雪" msgstr "晴有雨雪" -#: lib/utils/weather_icon.dart:291 +#: ./lib/utils/weather_icon.dart:291 msgid "晴有大雪" msgstr "晴有大雪" -#: lib/utils/weather_icon.dart:292 +#: ./lib/utils/weather_icon.dart:292 msgid "晴有雪珠" msgstr "晴有雪珠" -#: lib/utils/weather_icon.dart:293 +#: ./lib/utils/weather_icon.dart:293 msgid "晴有冰珠" msgstr "晴有冰珠" -#: lib/utils/weather_icon.dart:294 +#: ./lib/utils/weather_icon.dart:294 msgid "晴有陣雪" msgstr "晴有陣雪" -#: lib/utils/weather_icon.dart:295 +#: ./lib/utils/weather_icon.dart:295 msgid "晴陣雨雪" msgstr "晴陣雨雪" -#: lib/utils/weather_icon.dart:296 +#: ./lib/utils/weather_icon.dart:296 msgid "晴有雹" msgstr "晴有雹" -#: lib/utils/weather_icon.dart:297 +#: ./lib/utils/weather_icon.dart:297 msgid "晴有雷雨" msgstr "晴有雷雨" -#: lib/utils/weather_icon.dart:298 +#: ./lib/utils/weather_icon.dart:298 msgid "晴有雷雪" msgstr "晴有雷雪" -#: lib/utils/weather_icon.dart:299 +#: ./lib/utils/weather_icon.dart:299 msgid "晴有雷雹" msgstr "晴有雷雹" -#: lib/utils/weather_icon.dart:300 +#: ./lib/utils/weather_icon.dart:300 msgid "晴大雷雨" msgstr "晴大雷雨" -#: lib/utils/weather_icon.dart:301 +#: ./lib/utils/weather_icon.dart:301 msgid "晴大雷雹" msgstr "晴大雷雹" -#: lib/utils/weather_icon.dart:303 +#: ./lib/utils/weather_icon.dart:303 msgid "多雲" msgstr "多雲" -#: lib/utils/weather_icon.dart:304 +#: ./lib/utils/weather_icon.dart:304 msgid "多雲有霾" msgstr "多雲有霾" -#: lib/utils/weather_icon.dart:305 +#: ./lib/utils/weather_icon.dart:305 msgid "多雲有靄" msgstr "多雲有靄" -#: lib/utils/weather_icon.dart:306 +#: ./lib/utils/weather_icon.dart:306 msgid "多雲有閃電" msgstr "多雲有閃電" -#: lib/utils/weather_icon.dart:322 +#: ./lib/utils/weather_icon.dart:322 msgid "多雲伴有雷" msgstr "多雲伴有雷" -#: lib/utils/weather_icon.dart:308 +#: ./lib/utils/weather_icon.dart:308 msgid "多雲有霧" msgstr "多雲有霧" -#: lib/utils/weather_icon.dart:309 +#: ./lib/utils/weather_icon.dart:309 msgid "多雲有雨" msgstr "多雲有雨" -#: lib/utils/weather_icon.dart:310 +#: ./lib/utils/weather_icon.dart:310 msgid "多雲有雨雪" msgstr "多雲有雨雪" -#: lib/utils/weather_icon.dart:311 +#: ./lib/utils/weather_icon.dart:311 msgid "多雲有大雪" msgstr "多雲有大雪" -#: lib/utils/weather_icon.dart:312 +#: ./lib/utils/weather_icon.dart:312 msgid "多雲有雪珠" msgstr "多雲有雪珠" -#: lib/utils/weather_icon.dart:313 +#: ./lib/utils/weather_icon.dart:313 msgid "多雲有冰珠" msgstr "多雲有冰珠" -#: lib/utils/weather_icon.dart:314 +#: ./lib/utils/weather_icon.dart:314 msgid "多雲有陣雪" msgstr "多雲有陣雪" -#: lib/utils/weather_icon.dart:315 +#: ./lib/utils/weather_icon.dart:315 msgid "多雲陣雨雪" msgstr "多雲陣雨雪" -#: lib/utils/weather_icon.dart:316 +#: ./lib/utils/weather_icon.dart:316 msgid "多雲有雹" msgstr "多雲有雹" -#: lib/utils/weather_icon.dart:317 +#: ./lib/utils/weather_icon.dart:317 msgid "多雲有雷雨" msgstr "多雲有雷雨" -#: lib/utils/weather_icon.dart:318 +#: ./lib/utils/weather_icon.dart:318 msgid "多雲有雷雪" msgstr "多雲有雷雪" -#: lib/utils/weather_icon.dart:319 +#: ./lib/utils/weather_icon.dart:319 msgid "多雲有雷雹" msgstr "多雲有雷雹" -#: lib/utils/weather_icon.dart:320 +#: ./lib/utils/weather_icon.dart:320 msgid "多雲大雷雨" msgstr "多雲大雷雨" -#: lib/utils/weather_icon.dart:321 +#: ./lib/utils/weather_icon.dart:321 msgid "多雲大雷雹" msgstr "多雲大雷雹" -#: lib/utils/weather_icon.dart:323 +#: ./lib/utils/weather_icon.dart:323 msgid "陰" msgstr "陰" -#: lib/utils/weather_icon.dart:324 +#: ./lib/utils/weather_icon.dart:324 msgid "陰有霾" msgstr "陰有霾" -#: lib/utils/weather_icon.dart:325 +#: ./lib/utils/weather_icon.dart:325 msgid "陰有靄" msgstr "陰有靄" -#: lib/utils/weather_icon.dart:326 +#: ./lib/utils/weather_icon.dart:326 msgid "陰有閃電" msgstr "陰有閃電" -#: lib/utils/weather_icon.dart:342 +#: ./lib/utils/weather_icon.dart:342 msgid "陰天伴有雷" msgstr "陰天伴有雷" -#: lib/utils/weather_icon.dart:328 +#: ./lib/utils/weather_icon.dart:328 msgid "陰有霧" msgstr "陰有霧" -#: lib/utils/weather_icon.dart:329 +#: ./lib/utils/weather_icon.dart:329 msgid "陰有雨" msgstr "陰有雨" -#: lib/utils/weather_icon.dart:330 +#: ./lib/utils/weather_icon.dart:330 msgid "陰有雨雪" msgstr "陰有雨雪" -#: lib/utils/weather_icon.dart:331 +#: ./lib/utils/weather_icon.dart:331 msgid "陰有大雪" msgstr "陰有大雪" -#: lib/utils/weather_icon.dart:332 +#: ./lib/utils/weather_icon.dart:332 msgid "陰有雪珠" msgstr "陰有雪珠" -#: lib/utils/weather_icon.dart:333 +#: ./lib/utils/weather_icon.dart:333 msgid "陰有冰珠" msgstr "陰有冰珠" -#: lib/utils/weather_icon.dart:334 +#: ./lib/utils/weather_icon.dart:334 msgid "陰有陣雪" msgstr "陰有陣雪" -#: lib/utils/weather_icon.dart:335 +#: ./lib/utils/weather_icon.dart:335 msgid "陰陣雨雪" msgstr "陰陣雨雪" -#: lib/utils/weather_icon.dart:336 +#: ./lib/utils/weather_icon.dart:336 msgid "陰有雹" msgstr "陰有雹" -#: lib/utils/weather_icon.dart:337 +#: ./lib/utils/weather_icon.dart:337 msgid "陰有雷雨" msgstr "陰有雷雨" -#: lib/utils/weather_icon.dart:338 +#: ./lib/utils/weather_icon.dart:338 msgid "陰有雷雪" msgstr "陰有雷雪" -#: lib/utils/weather_icon.dart:339 +#: ./lib/utils/weather_icon.dart:339 msgid "陰有雷雹" msgstr "陰有雷雹" -#: lib/utils/weather_icon.dart:340 +#: ./lib/utils/weather_icon.dart:340 msgid "陰大雷雨" msgstr "陰大雷雨" -#: lib/utils/weather_icon.dart:341 +#: ./lib/utils/weather_icon.dart:341 msgid "陰大雷雹" msgstr "陰大雷雹" -#, fuzzy -#~ msgid "同步通知設定" -#~ msgstr "同步通知設定" - -#~ msgid "" -#~ "感謝您的支持!❤️\n" -#~ "您所支付的款項將用於伺服器維護用途。若您有任何問題,歡迎於付款前與我們聯" -#~ "繫。" -#~ msgstr "" -#~ "感謝您的支持!❤️\n" -#~ "您所支付的款項將用於伺服器維護用途。若您有任何問題,歡迎於付款前與我們聯" -#~ "繫。" - -#~ msgid "地震類與氣象類圖層互斥" -#~ msgstr "地震類與氣象類圖層互斥" +#: ./lib/api/model/location/location.dart:82 +msgid "{city}{cityLevel} {town}{townLevel}" +msgstr "{city}{cityLevel} {town}{townLevel}" + +#: ./lib/api/model/location/location.dart:95 +msgid "{city} {town}" +msgstr "{city} {town}" + +#: ./lib/api/model/location/location.dart:104 +msgid "{city}{cityLevel}" +msgstr "{city}{cityLevel}" + +#: ./lib/api/model/location/location.dart:113 +msgid "{town}{townLevel}" +msgstr "{town}{townLevel}" diff --git a/crowdin.yml b/crowdin.yml index 52333b66d..2de49148f 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,3 +1,8 @@ files: - - source: /assets/translations/strings.pot + - source: /.crowdin/strings.pot translation: /assets/translations/%osx_locale%.po + - source: /.crowdin/*.csv + translation: /assets/translations/%original_file_name% + multilingual: 1 + first_line_contains_header: 1 + scheme: 'identifier,source_phrase,en,ja,ko,ru,vi,zh-CN' diff --git a/docs/sound.mdx b/docs/sound.mdx index 594af7122..636a7f211 100644 --- a/docs/sound.mdx +++ b/docs/sound.mdx @@ -59,9 +59,14 @@ # 雷雨即時訊息 +## 重大 + +- 條件:所在地(鄉鎮)發布山區暴雨時。 +- 音效:rain + ## 一般 -- 條件:所在地(鄉鎮)發布雷雨即時訊息或山區暴雨時。 +- 條件:所在地(鄉鎮)發布雷雨即時訊息時。 - 音效:rain # 天氣警特報 @@ -76,28 +81,28 @@ - 條件:所在地(鄉鎮)發布上述除外燈號之天氣警特報。 - 音效:weather -# 避難資訊(防空、土石流、淹水、堰塞湖) +# 防災資訊(防空、土石流、淹水、堰塞湖) ## 重大 -- 條件:所在地(鄉鎮)發布避難警訊時。 +- 條件:所在地(鄉鎮)發布防災警訊時。 - 音效:warn ## 一般 -- 條件:所在地(鄉鎮)發布避難資訊時。 +- 條件:所在地(鄉鎮)發布防災資訊時。 - 音效:warn # 海嘯資訊 ## 重大 -- 條件:海嘯警報發布時,沿海地區鄉鎮。 +- 條件:海嘯警報發布時。 - 音效:tsunami ## 一般 -- 條件:海嘯警報發布時,上述除外地區。 +- 條件:海嘯消息發布時。 - 音效:normal ## 太平洋海嘯消息(無聲) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 5d793b88b..dc2e37211 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -13,81 +13,46 @@ PODS: - IosAwnFcmCore (~> 0.10.1) - device_info_plus (0.0.1): - Flutter - - Firebase/CoreOnly (11.10.0): - - FirebaseCore (~> 11.10.0) - - Firebase/Crashlytics (11.10.0): + - Firebase/CoreOnly (11.15.0): + - FirebaseCore (~> 11.15.0) + - Firebase/Messaging (11.15.0): - Firebase/CoreOnly - - FirebaseCrashlytics (~> 11.10.0) - - Firebase/Messaging (11.10.0): - - Firebase/CoreOnly - - FirebaseMessaging (~> 11.10.0) - - firebase_core (3.13.0): - - Firebase/CoreOnly (= 11.10.0) - - Flutter - - firebase_crashlytics (4.3.5): - - Firebase/Crashlytics (= 11.10.0) - - firebase_core + - FirebaseMessaging (~> 11.15.0) + - firebase_core (3.15.2): + - Firebase/CoreOnly (= 11.15.0) - Flutter - - firebase_messaging (15.2.5): - - Firebase/Messaging (= 11.10.0) + - firebase_messaging (15.2.10): + - Firebase/Messaging (= 11.15.0) - firebase_core - Flutter - - FirebaseCore (11.10.0): - - FirebaseCoreInternal (~> 11.10.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Logger (~> 8.0) - - FirebaseCoreExtension (11.10.0): - - FirebaseCore (~> 11.10.0) - - FirebaseCoreInternal (11.10.0): - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FirebaseCrashlytics (11.10.0): - - FirebaseCore (~> 11.10.0) - - FirebaseInstallations (~> 11.0) - - FirebaseRemoteConfigInterop (~> 11.0) - - FirebaseSessions (~> 11.0) - - GoogleDataTransport (~> 10.0) - - GoogleUtilities/Environment (~> 8.0) - - nanopb (~> 3.30910.0) - - PromisesObjC (~> 2.4) - - FirebaseInstallations (11.10.0): - - FirebaseCore (~> 11.10.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) + - FirebaseCore (11.15.0): + - FirebaseCoreInternal (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/Logger (~> 8.1) + - FirebaseCoreInternal (11.15.0): + - "GoogleUtilities/NSData+zlib (~> 8.1)" + - FirebaseInstallations (11.15.0): + - FirebaseCore (~> 11.15.0) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/UserDefaults (~> 8.1) - PromisesObjC (~> 2.4) - - FirebaseMessaging (11.10.0): - - FirebaseCore (~> 11.10.0) + - FirebaseMessaging (11.15.0): + - FirebaseCore (~> 11.15.0) - FirebaseInstallations (~> 11.0) - GoogleDataTransport (~> 10.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Reachability (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.1) + - GoogleUtilities/Environment (~> 8.1) + - GoogleUtilities/Reachability (~> 8.1) + - GoogleUtilities/UserDefaults (~> 8.1) - nanopb (~> 3.30910.0) - - FirebaseRemoteConfigInterop (11.15.0) - - FirebaseSessions (11.10.0): - - FirebaseCore (~> 11.10.0) - - FirebaseCoreExtension (~> 11.10.0) - - FirebaseInstallations (~> 11.0) - - GoogleDataTransport (~> 10.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) - - nanopb (~> 3.30910.0) - - PromisesSwift (~> 2.1) - Flutter (1.0.0) - - flutter_background_service_ios (0.0.3): - - Flutter - flutter_icmp_ping (0.0.1): - Flutter - - flutter_local_notifications (0.0.1): - - Flutter - fluttertoast (0.0.2): - Flutter - gal (1.0.0): - Flutter - FlutterMacOS - - geolocator_apple (1.2.0): - - Flutter - - FlutterMacOS - GoogleDataTransport (10.1.0): - nanopb (~> 3.30910.0) - PromisesObjC (~> 2.4) @@ -157,8 +122,6 @@ PODS: - permission_handler_apple (9.3.0): - Flutter - PromisesObjC (2.4.0) - - PromisesSwift (2.4.0): - - PromisesObjC (= 2.4.0) - share_plus (0.0.1): - Flutter - shared_preferences_foundation (0.0.1): @@ -176,15 +139,11 @@ DEPENDENCIES: - awesome_notifications_fcm (from `.symlinks/plugins/awesome_notifications_fcm/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - Flutter (from `Flutter`) - - flutter_background_service_ios (from `.symlinks/plugins/flutter_background_service_ios/ios`) - flutter_icmp_ping (from `.symlinks/plugins/flutter_icmp_ping/ios`) - - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - gal (from `.symlinks/plugins/gal/darwin`) - - geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`) - in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`) - maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) @@ -199,13 +158,9 @@ SPEC REPOS: trunk: - Firebase - FirebaseCore - - FirebaseCoreExtension - FirebaseCoreInternal - - FirebaseCrashlytics - FirebaseInstallations - FirebaseMessaging - - FirebaseRemoteConfigInterop - - FirebaseSessions - GoogleDataTransport - GoogleUtilities - IosAwnCore @@ -213,7 +168,6 @@ SPEC REPOS: - MapLibre - nanopb - PromisesObjC - - PromisesSwift EXTERNAL SOURCES: awesome_notifications: @@ -226,24 +180,16 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/device_info_plus/ios" firebase_core: :path: ".symlinks/plugins/firebase_core/ios" - firebase_crashlytics: - :path: ".symlinks/plugins/firebase_crashlytics/ios" firebase_messaging: :path: ".symlinks/plugins/firebase_messaging/ios" Flutter: :path: Flutter - flutter_background_service_ios: - :path: ".symlinks/plugins/flutter_background_service_ios/ios" flutter_icmp_ping: :path: ".symlinks/plugins/flutter_icmp_ping/ios" - flutter_local_notifications: - :path: ".symlinks/plugins/flutter_local_notifications/ios" fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" gal: :path: ".symlinks/plugins/gal/darwin" - geolocator_apple: - :path: ".symlinks/plugins/geolocator_apple/darwin" in_app_purchase_storekit: :path: ".symlinks/plugins/in_app_purchase_storekit/darwin" maplibre_gl: @@ -264,46 +210,37 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - awesome_notifications: 0f432b28098d193920b11a44cfa9d2d9313a3888 - awesome_notifications_core: 429c28df8746780a474de177e5acde33af87da63 - awesome_notifications_fcm: ad14f584c81e2488ae4310ab96331327dcbb5368 - device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe - Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2 - firebase_core: 2d4534e7b489907dcede540c835b48981d890943 - firebase_crashlytics: 961a0812ba79ed8f89a8d5d1e3763daa6267a87a - firebase_messaging: 75bc93a4df25faccad67f6662ae872ac9ae69b64 - FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7 - FirebaseCoreExtension: 6f357679327f3614e995dc7cf3f2d600bdc774ac - FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679 - FirebaseCrashlytics: 84b073c997235740e6a951b7ee49608932877e5c - FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3 - FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9 - FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa - FirebaseSessions: 9b3b30947b97a15370e0902ee7a90f50ef60ead6 + awesome_notifications: dd5518ff1c80be03d4f1c40f04da9d9cc2a37af5 + awesome_notifications_core: d02eed89738fa362d56cbd372850e9adcd2c6bef + awesome_notifications_fcm: 707931990883faf918db11438bdddded93b2b3a6 + device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 + Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e + firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c + firebase_messaging: bf6697c61f31c7cc0f654131212ff04c0115c2c7 + FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e + FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 + FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 + FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_background_service_ios: 00d31bdff7b4bfe06d32375df358abe0329cf87e - flutter_icmp_ping: 47c1df3440c18ddd39fc457e607bb3b42d4a339f - flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb - fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 - gal: baecd024ebfd13c441269ca7404792a7152fde89 - geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e + flutter_icmp_ping: 2b159955eee0c487c766ad83fec224ae35e7c935 + fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f + gal: 6a522c75909f1244732d4596d11d6a2f86ff37a5 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 - in_app_purchase_storekit: d1a48cb0f8b29dbf5f85f782f5dd79b21b90a5e6 + in_app_purchase_storekit: a1ce04056e23eecc666b086040239da7619cd783 IosAwnCore: 653786a911089012092ce831f2945cd339855a89 IosAwnFcmCore: 1bdb9054b2e00187d00f1ffcfbb1855949a7b82f MapLibre: 69e572367f4ef6287e18246cfafc39c80cdcabcd - maplibre_gl: 3c924e44725147b03dda33430ad216005b40555f + maplibre_gl: 753f55d763a81cbdba087d02af02d12206e6f94e nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 - permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 - share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a - shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 - sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 - url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe PODFILE CHECKSUM: 3d88bce62bfe048ac33ca00d3fb1bc02caeda4d3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 92a922e97..0eb7ef800 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -65,8 +65,6 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 4B4531DD011F7A688ACAA691 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 5228AD5A2C2EE45D007635F5 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - 522D48FF2DFD33EF0030AB0C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 522D49002DFD33F20030AB0C /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/InfoPlist.strings; sourceTree = ""; }; 529C27C92C93F7B900AAFAB6 /* zh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh; path = zh.lproj/InfoPlist.strings; sourceTree = ""; }; 529C27CC2C93F7BC00AAFAB6 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/InfoPlist.strings; sourceTree = ""; }; 529C27CF2C947EFB00AAFAB6 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -491,8 +489,6 @@ 529C27CC2C93F7BC00AAFAB6 /* ko */, 529C27CF2C947EFB00AAFAB6 /* ja */, 529C27DC2C97019E00AAFAB6 /* zh_TW */, - 522D48FF2DFD33EF0030AB0C /* en */, - 522D49002DFD33F20030AB0C /* vi */, ); name = InfoPlist.strings; sourceTree = ""; diff --git a/ios/Runner/en.lproj/InfoPlist.strings b/ios/Runner/en.lproj/InfoPlist.strings deleted file mode 100644 index e69de29bb..000000000 diff --git a/ios/Runner/vi.lproj/InfoPlist.strings b/ios/Runner/vi.lproj/InfoPlist.strings deleted file mode 100644 index e69de29bb..000000000 diff --git a/l10n.yaml b/l10n.yaml deleted file mode 100644 index 8119ecfd5..000000000 --- a/l10n.yaml +++ /dev/null @@ -1,4 +0,0 @@ -arb-dir: lib/l10n -template-arb-file: app_zh_TW.arb -output-localization-file: app_localizations.dart -synthetic-package: false \ No newline at end of file diff --git a/lib/api/exptech.dart b/lib/api/exptech.dart index 60c467718..e0412a74d 100644 --- a/lib/api/exptech.dart +++ b/lib/api/exptech.dart @@ -1,6 +1,9 @@ import 'dart:convert'; import 'dart:io'; +import 'package:http/http.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; + import 'package:dpip/api/model/announcement.dart'; import 'package:dpip/api/model/changelog/changelog.dart'; import 'package:dpip/api/model/crowdin/localization_progress.dart'; @@ -24,7 +27,6 @@ import 'package:dpip/core/preference.dart'; import 'package:dpip/models/settings/notify.dart'; import 'package:dpip/utils/extensions/response.dart'; import 'package:dpip/utils/extensions/string.dart'; -import 'package:http/http.dart'; class ExpTech { String? apikey; @@ -32,7 +34,7 @@ class ExpTech { ExpTech({this.apikey}); Future getReport(String reportId) async { - final requestUrl = Route.report(reportId); + final requestUrl = Routes.report(reportId); final res = await get(requestUrl); @@ -55,7 +57,7 @@ class ExpTech { int? minDepth = 0, int? maxDepth = 700, }) async { - final requestUrl = Route.reportList( + final requestUrl = Routes.reportList( limit: limit, page: page, minIntensity: minIntensity, @@ -78,7 +80,7 @@ class ExpTech { } Future getRts([int? time]) async { - var requestUrl = Route.rts(); + var requestUrl = Routes.rts(); if (time != null) { requestUrl = Uri.parse( @@ -102,7 +104,7 @@ class ExpTech { } Future> getEew([int? time]) async { - var requestUrl = Route.eew(); + var requestUrl = Routes.eew(); if (time != null) { requestUrl = Uri.parse( @@ -126,7 +128,7 @@ class ExpTech { } Future getNtp() async { - final requestUrl = Route.ntp(); + final requestUrl = Routes.ntp(); final res = await get(requestUrl); @@ -138,7 +140,7 @@ class ExpTech { } Future> getStations() async { - final requestUrl = Route.station(); + final requestUrl = Routes.station(); final res = await get(requestUrl); @@ -152,7 +154,7 @@ class ExpTech { } Future getTsunami(String tsuId) async { - final requestUrl = Route.tsunami(tsuId); + final requestUrl = Routes.tsunami(tsuId); final res = await get(requestUrl); @@ -166,7 +168,7 @@ class ExpTech { } Future> getTsunamiList() async { - final requestUrl = Route.tsunamiList(); + final requestUrl = Routes.tsunamiList(); final res = await get(requestUrl); @@ -180,7 +182,7 @@ class ExpTech { } Future> getLocalizationProgress() async { - final requestUrl = Route.locale(); + final requestUrl = Routes.locale(); final res = await get(requestUrl); @@ -194,7 +196,7 @@ class ExpTech { } Future> getRadarList() async { - final requestUrl = Route.radarList(); + final requestUrl = Routes.radarList(); final res = await get(requestUrl); @@ -208,7 +210,7 @@ class ExpTech { } Future> getWeatherList() async { - final requestUrl = Route.weatherList(); + final requestUrl = Routes.weatherList(); final res = await get(requestUrl); @@ -222,7 +224,7 @@ class ExpTech { } Future> getWeather(String time) async { - final requestUrl = Route.weather(time); + final requestUrl = Routes.weather(time); final res = await get(requestUrl); @@ -236,7 +238,7 @@ class ExpTech { } Future getWeatherRealtime(String region) async { - final requestUrl = Route.weatherRealtime(region); + final requestUrl = Routes.weatherRealtime(region); final res = await get(requestUrl); @@ -250,7 +252,7 @@ class ExpTech { } Future> getRainList() async { - final requestUrl = Route.rainList(); + final requestUrl = Routes.rainList(); final res = await get(requestUrl); @@ -264,7 +266,7 @@ class ExpTech { } Future> getRain(String time) async { - final requestUrl = Route.rain(time); + final requestUrl = Routes.rain(time); final res = await get(requestUrl); @@ -278,7 +280,7 @@ class ExpTech { } Future getTyphoonImagesList() async { - final requestUrl = Route.typhoonImagesList(); + final requestUrl = Routes.typhoonImagesList(); final res = await get(requestUrl); @@ -292,7 +294,7 @@ class ExpTech { } Future> getLightningList() async { - final requestUrl = Route.lightningList(); + final requestUrl = Routes.lightningList(); final res = await get(requestUrl); @@ -306,7 +308,7 @@ class ExpTech { } Future> getTyphoonGeojson() async { - final requestUrl = Route.typhoonGeojson(); + final requestUrl = Routes.typhoonGeojson(); final res = await get(requestUrl); @@ -320,7 +322,7 @@ class ExpTech { } Future> getLightning(String time) async { - final requestUrl = Route.lightning(time); + final requestUrl = Routes.lightning(time); final res = await get(requestUrl); @@ -334,7 +336,7 @@ class ExpTech { } Future> getRealtime() async { - final requestUrl = Route.realtime(); + final requestUrl = Routes.realtime(); final res = await get(requestUrl); @@ -348,7 +350,7 @@ class ExpTech { } Future> getHistory() async { - final requestUrl = Route.history(); + final requestUrl = Routes.history(); final res = await get(requestUrl); @@ -362,7 +364,7 @@ class ExpTech { } Future> getRealtimeRegion(String region) async { - final requestUrl = Route.realtimeRegion(region); + final requestUrl = Routes.realtimeRegion(region); final res = await get(requestUrl); @@ -376,7 +378,7 @@ class ExpTech { } Future> getHistoryRegion(String region) async { - final requestUrl = Route.historyRegion(region); + final requestUrl = Routes.historyRegion(region); final res = await get(requestUrl); @@ -390,7 +392,7 @@ class ExpTech { } Future> getSupport() async { - final requestUrl = Route.support(); + final requestUrl = Routes.support(); final res = await get(requestUrl); @@ -416,7 +418,7 @@ class ExpTech { } Future> getAnnouncement() async { - final requestUrl = Route.announcement(); + final requestUrl = Routes.announcement(); final res = await get(requestUrl); @@ -430,7 +432,7 @@ class ExpTech { } Future> getNotificationHistory() async { - final requestUrl = Route.notificationHistory(); + final requestUrl = Routes.notificationHistory(); final res = await get(requestUrl); @@ -444,7 +446,7 @@ class ExpTech { } Future> getStatus() async { - final requestUrl = Route.status(); + final requestUrl = Routes.status(); final res = await get(requestUrl); @@ -458,7 +460,7 @@ class ExpTech { } Future getMeteorStation(String id) async { - final requestUrl = Route.meteorStation(id); + final requestUrl = Routes.meteorStation(id); final res = await get(requestUrl); @@ -472,7 +474,7 @@ class ExpTech { } Future> getEvent(String id) async { - final requestUrl = Route.event(id); + final requestUrl = Routes.event(id); final res = await get(requestUrl); @@ -486,8 +488,8 @@ class ExpTech { } /// 回傳所在地 - Future updateDeviceLocation({required String token, required String lat, required String lng}) async { - final requestUrl = Route.location(token: token, lat: lat, lng: lng); + Future updateDeviceLocation({required String token, required LatLng coordinates}) async { + final requestUrl = Routes.location(token: token, lat: '${coordinates.latitude}', lng: '${coordinates.longitude}'); final res = await get(requestUrl); @@ -504,7 +506,7 @@ class ExpTech { /// 取得通知 Future getNotify({required String token}) async { - final requestUrl = Route.notify(token: token); + final requestUrl = Routes.notify(token: token); final res = await get(requestUrl); @@ -523,7 +525,7 @@ class ExpTech { required NotifyChannel channel, required Enum status, }) async { - final requestUrl = Route.notifyStatus(token: token, channel: channel, status: status); + final requestUrl = Routes.notifyStatus(token: token, channel: channel, status: status); final res = await get(requestUrl); @@ -542,7 +544,7 @@ class ExpTech { required List status, required List status_dev, }) async { - final requestUrl = Route.networkInfo(); + final requestUrl = Routes.networkInfo(); String body = jsonEncode({'ip': ip, 'isp': isp, 'status': status, 'status_dev': status_dev}); diff --git a/lib/api/model/history/history.dart b/lib/api/model/history/history.dart index e10d05acb..aef30b2bf 100644 --- a/lib/api/model/history/history.dart +++ b/lib/api/model/history/history.dart @@ -29,6 +29,9 @@ enum HistoryType { @JsonValue('extremely-torrential-rain') extremelyTorrentialRain, + + @JsonValue('workSchlClos') + workAndClassSuspension, } @JsonSerializable() diff --git a/lib/api/model/location/location.dart b/lib/api/model/location/location.dart index 3538d525b..5cb2cee9e 100644 --- a/lib/api/model/location/location.dart +++ b/lib/api/model/location/location.dart @@ -1,17 +1,300 @@ +import 'package:i18n_extension/i18n_extension.dart'; import 'package:json_annotation/json_annotation.dart'; +import 'package:dpip/core/i18n.dart'; +import 'package:dpip/global.dart'; + part 'location.g.dart'; +/// Represents a geographical location in Taiwan with administrative hierarchy. +/// +/// This class encapsulates location data including the city and town names, their administrative levels (縣/市/區/鄉/ +/// 鎮), and geographical coordinates. It provides localized display methods for different presentation formats. +/// +/// Example: +/// ```dart +/// const location = Location( +/// city: '臺北', +/// town: '信義', +/// lat: 25.0330, +/// lng: 121.5654, +/// cityLevel: '市', +/// townLevel: '區', +/// ); +/// +/// print(location.dynamicName); // "臺北市 信義區" or shorter if too long +/// ``` @JsonSerializable() class Location { + /// The city name (e.g., "臺北", "高雄"). + /// + /// This represents the primary administrative division in Taiwan's government hierarchy. final String city; + + /// The town/district name (e.g., "信義", "前金"). + /// + /// This represents the secondary administrative division within a city. final String town; + + /// The latitude coordinate in decimal degrees. + /// + /// Valid range is approximately 21.5° to 25.5° for Taiwan. final double lat; + + /// The longitude coordinate in decimal degrees. + /// + /// Valid range is approximately 120° to 122° for Taiwan. final double lng; - const Location({required this.city, required this.town, required this.lat, required this.lng}); + /// The administrative level of the city (e.g., "市", "縣"). + /// + /// This indicates the type of primary administrative division: + /// - "市" for special municipalities and provincial cities + /// - "縣" for counties + final String cityLevel; + + /// The administrative level of the town (e.g., "區", "鄉", "鎮"). + /// + /// This indicates the type of secondary administrative division: + /// - "區" for districts (in cities) + /// - "鄉" for townships + /// - "鎮" for towns + final String townLevel; + + /// Creates a new [Location] instance. + /// + /// All parameters are required and represent the administrative and geographical data for a location in Taiwan. + const Location({ + required this.city, + required this.town, + required this.lat, + required this.lng, + required this.cityLevel, + required this.townLevel, + }); + + /// Returns the full localized location name with both city and town levels. + /// + /// Format: `"{city}{cityLevel} {town}{townLevel}"`\ + /// Example: "臺北市 信義區" or "Taipei City Xinyi District" + /// + /// This is the most complete form of the location name including all administrative level indicators. + String get cityTownWithLevel => '{city}{cityLevel} {town}{townLevel}'.i18n.args({ + 'city': city.locationName, + 'cityLevel': cityLevel.locationName, + 'town': town.locationName, + 'townLevel': townLevel.locationName, + }); + + /// Returns the localized location name without administrative levels. + /// + /// Format: `"{city} {town}"`\ + /// Example: "臺北 信義" or "Taipei Xinyi" + /// + /// This provides a cleaner, shorter display format without the administrative level suffixes. + String get cityTown => '{city} {town}'.i18n.args({'city': city.locationName, 'town': town.locationName}); + /// Returns the localized city name with its administrative level. + /// + /// Format: `"{city}{cityLevel}"`\ + /// Example: "臺北市" or "Taipei City" + /// + /// Use this when you only need to display the primary administrative division. + String get cityWithLevel => + '{city}{cityLevel}'.i18n.args({'city': city.locationName, 'cityLevel': cityLevel.locationName}); + + /// Returns the localized town name with its administrative level. + /// + /// Format: `"{town}{townLevel}"`\ + /// Example: "信義區" or "Xinyi District" + /// + /// Use this when you only need to display the secondary administrative division. + String get townWithLevel => + '{town}{townLevel}'.i18n.args({'town': town.locationName, 'townLevel': townLevel.locationName}); + + /// Returns a localized location name that adapts to available space. + /// + /// This method implements a fallback strategy to provide the most appropriate location name based on length + /// constraints: + /// + /// 1. First tries [cityTownWithLevel] (full format) + /// 2. If too long (>24 chars), falls back to [townWithLevel] + /// 3. If still too long, falls back to just [town] name + /// + /// This is ideal for UI elements with limited space where you want to show as much location detail as possible while + /// maintaining readability. + /// + /// Example progression: + /// - `"新北市板橋區"` → `"板橋區"` → `"板橋"` + /// - `"Qianzhen District, Kaohsiung City"` → `"Qianzhen District"` → `"Qianzhen"` + String get dynamicName { + // Try full format first + String content = cityTownWithLevel; + + // Fall back to town with level if too long + if (content.length > 24) { + content = townWithLevel; + } + + // Fall back to town name only if still too long + if (content.length > 24) { + content = town; + } + + return content; + } + + /// Creates a [Location] instance from a JSON map. + /// + /// This factory constructor is generated by `json_annotation` and is used for deserializing location data from JSON + /// sources such as APIs or local storage. + /// + /// Example: + /// ```dart + /// final json = { + /// 'city': '臺北', + /// 'town': '信義', + /// 'lat': 25.0330, + /// 'lng': 121.5654, + /// 'cityLevel': '市', + /// 'townLevel': '區', + /// }; + /// final location = Location.fromJson(json); + /// ``` factory Location.fromJson(Map json) => _$LocationFromJson(json); + /// Converts this [Location] instance to a JSON map. + /// + /// This method is generated by `json_annotation` and is used for serializing location data to JSON format for storage + /// or transmission. + /// + /// Returns a [Map] containing all the location properties with their original keys. Map toJson() => _$LocationToJson(this); + + /// Attempts to parse a Chinese location string into a [Location] instance. + /// + /// The input string should be in Chinese and follow the format `"{city}{cityLevel}{town}{townLevel}"`, but can have + /// variations such as: + /// - Missing administrative levels: `"臺北信義"` or `"臺北市信義"` + /// - Extra spaces: `"臺北市 信義區"` or `"臺北 信義"` + /// - Different combinations of levels + /// + /// Returns `null` if: + /// - The city name cannot be found in the location database + /// - The town name cannot be found within the identified city + /// - The input string is empty or invalid + /// + /// Examples: + /// ```dart + /// Location.tryParse("臺北市信義區"); // ✓ Full format + /// Location.tryParse("臺北信義"); // ✓ No levels + /// Location.tryParse("臺北市 信義區"); // ✓ With spaces + /// Location.tryParse("臺北信義區"); // ✓ Mixed levels + /// Location.tryParse("不存在的地方"); // ✗ Returns null + /// ``` + /// + /// This method searches through the global location map (`Global.location`) to find matching city and town + /// combinations. + static Location? tryParse(String input) { + if (input.trim().isEmpty) return null; + + // Clean the input: remove all spaces and normalize + final cleanInput = input.replaceAll(RegExp(r'\s+'), '').toLowerCase(); + + // Normalize traditional/simplified characters for better matching + final normalizedInput = _normalizeChineseCharacters(cleanInput); + + // Try to find the best matching location + Location? bestMatch; + int bestMatchScore = 0; + + // Iterate through all locations in the database + for (final locationEntry in Global.location.entries) { + final location = locationEntry.value; + + // Generate possible Chinese representations of this location + final possibleFormats = [ + '${location.city}${location.cityLevel}${location.town}${location.townLevel}', // Full format + '${location.city}${location.cityLevel}${location.town}', // No town level + '${location.city}${location.town}${location.townLevel}', // No city level + '${location.city}${location.town}', // No levels + ]; + + // Check each possible format against the input + for (final format in possibleFormats) { + final normalizedFormat = _normalizeChineseCharacters(format.toLowerCase()); + + if (normalizedInput == normalizedFormat) { + // Exact match found - return immediately + return location; + } + + // Calculate match score for partial matches + final score = _calculateMatchScore(normalizedInput, normalizedFormat); + if (score > bestMatchScore) { + bestMatchScore = score; + bestMatch = location; + } + } + } + + // Return the best match if it's good enough (threshold: 90% similarity for safety) + return bestMatchScore >= 90 ? bestMatch : null; + } + + /// Calculates a match score between input and target strings. + /// + /// Returns a score from 0-100 where 100 is a perfect match. + /// Uses a simple similarity algorithm based on common character sequences. + static int _calculateMatchScore(String input, String target) { + if (input == target) return 100; + if (input.isEmpty || target.isEmpty) return 0; + + // Check if input is a substring of target or vice versa + if (target.contains(input)) { + return (input.length * 100) ~/ target.length; + } + if (input.contains(target)) { + return (target.length * 100) ~/ input.length; + } + + // Count matching characters in order + int matches = 0; + int inputIndex = 0; + int targetIndex = 0; + + while (inputIndex < input.length && targetIndex < target.length) { + if (input[inputIndex] == target[targetIndex]) { + matches++; + inputIndex++; + targetIndex++; + } else { + targetIndex++; + } + } + + return (matches * 100) ~/ input.length; + } + + /// Normalizes Chinese characters for better matching between traditional and simplified forms. + /// + /// This method handles common character variations that might appear in user input + /// vs. the database, ensuring "台中" matches "臺中", etc. + static String _normalizeChineseCharacters(String input) { + // Map of common simplified -> traditional character pairs used in Taiwan location names + const charMap = { + '台': '臺', // Taiwan/Platform + '县': '縣', // County + '区': '區', // District + '乡': '鄉', // Township + '镇': '鎮', // Town + // Add more mappings as needed + }; + + String result = input; + for (final entry in charMap.entries) { + result = result.replaceAll(entry.key, entry.value); + } + return result; + } } diff --git a/lib/api/model/report/earthquake_report.dart b/lib/api/model/report/earthquake_report.dart index 3c295ee36..b30e93a08 100644 --- a/lib/api/model/report/earthquake_report.dart +++ b/lib/api/model/report/earthquake_report.dart @@ -1,11 +1,13 @@ import 'package:collection/collection.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:timezone/timezone.dart'; + import 'package:dpip/api/model/report/area_intensity.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/map_utils.dart'; import 'package:dpip/utils/parser.dart'; -import 'package:json_annotation/json_annotation.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:timezone/timezone.dart'; part 'earthquake_report.g.dart'; @@ -203,7 +205,7 @@ class EarthquakeReport { .toList(); final cross = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(latlng.toGeoJsonCoordinates()) + ..setGeometry(latlng.asGeoJsonCooridnate) ..setProperty('icon', 'cross-7') ..setProperty('magnitude', magnitude); diff --git a/lib/api/model/report/partial_earthquake_report.dart b/lib/api/model/report/partial_earthquake_report.dart index 3a1f7ae15..fcd469f94 100644 --- a/lib/api/model/report/partial_earthquake_report.dart +++ b/lib/api/model/report/partial_earthquake_report.dart @@ -1,10 +1,13 @@ -import 'package:dpip/utils/geojson.dart'; -import 'package:dpip/utils/parser.dart'; import 'package:flutter/material.dart'; + import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:timezone/timezone.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; +import 'package:dpip/utils/parser.dart'; + part 'partial_earthquake_report.g.dart'; @JsonSerializable() @@ -163,7 +166,7 @@ class PartialEarthquakeReport { GeoJsonFeatureBuilder toGeoJsonFeature() { return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) .setId(time.millisecondsSinceEpoch) - .setGeometry(latlng.toGeoJsonCoordinates()) + .setGeometry(latlng.asGeoJsonCooridnate) .setProperty('icon', 'cross-$intensity') .setProperty('magnitude', magnitude) .setProperty('intensity', intensity) diff --git a/lib/api/model/rts/rts.dart b/lib/api/model/rts/rts.dart index 04433c24b..112977a51 100644 --- a/lib/api/model/rts/rts.dart +++ b/lib/api/model/rts/rts.dart @@ -1,8 +1,10 @@ +import 'package:json_annotation/json_annotation.dart'; + import 'package:dpip/api/model/rts/rts_intensity.dart'; import 'package:dpip/api/model/rts/rts_station.dart'; import 'package:dpip/core/providers.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; -import 'package:json_annotation/json_annotation.dart'; part 'rts.g.dart'; @@ -38,7 +40,7 @@ class Rts { } return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(latlng.toGeoJsonCoordinates()) + ..setGeometry(latlng.asGeoJsonCooridnate) ..setProperty('id', id) ..setProperty('I', s.I) ..setProperty('i', s.i) diff --git a/lib/api/model/station_intensity.dart b/lib/api/model/station_intensity.dart index d46c0435a..918c96544 100644 --- a/lib/api/model/station_intensity.dart +++ b/lib/api/model/station_intensity.dart @@ -1,7 +1,9 @@ -import 'package:dpip/utils/geojson.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; + part 'station_intensity.g.dart'; @JsonSerializable() @@ -25,8 +27,8 @@ class StationIntensity { Map toJson() => _$StationIntensityToJson(this); GeoJsonFeatureBuilder toGeoJsonFeature() { - return GeoJsonFeatureBuilder( - GeoJsonFeatureType.Point, - ).setGeometry(latlng.toGeoJsonCoordinates()).setProperty('icon', 'intensity-$intensity'); + return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) + ..setGeometry(latlng.asGeoJsonCooridnate) + ..setProperty('icon', 'intensity-$intensity'); } } diff --git a/lib/api/model/weather/rain.dart b/lib/api/model/weather/rain.dart index d4af0e2f9..c17cd37a2 100644 --- a/lib/api/model/weather/rain.dart +++ b/lib/api/model/weather/rain.dart @@ -1,8 +1,10 @@ -import 'package:dpip/utils/geojson.dart'; -import 'package:dpip/widgets/map/latlng_altitude.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; +import 'package:dpip/widgets/map/latlng_altitude.dart'; + part 'rain.g.dart'; @JsonSerializable() @@ -21,7 +23,7 @@ class RainStation { GeoJsonFeatureBuilder toFeatureBuilder() => GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(station.latlng.toGeoJsonCoordinates()) + ..setGeometry(station.latlng.asGeoJsonCooridnate) ..setProperty('id', id) ..setProperty('name', station.name) ..setProperty('county', station.county) diff --git a/lib/api/model/weather/weather.dart b/lib/api/model/weather/weather.dart index bb1bfcec1..49e745784 100644 --- a/lib/api/model/weather/weather.dart +++ b/lib/api/model/weather/weather.dart @@ -1,7 +1,9 @@ -import 'package:dpip/utils/geojson.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; + part 'weather.g.dart'; @JsonSerializable() @@ -25,7 +27,7 @@ class WeatherStation { GeoJsonFeatureBuilder toFeatureBuilder() { final direction = (data.wind.direction + 180) % 360; return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - .setGeometry(station.latlng.toGeoJsonCoordinates()) + .setGeometry(station.latlng.asGeoJsonCooridnate) .setProperty('id', id) .setProperty('name', station.name) .setProperty('county', station.county) diff --git a/lib/api/route.dart b/lib/api/route.dart index 5817d6af2..84da3210f 100644 --- a/lib/api/route.dart +++ b/lib/api/route.dart @@ -4,7 +4,9 @@ import 'dart:math'; import 'package:dpip/global.dart'; import 'package:dpip/models/settings/notify.dart'; -class Route { +class Routes { + Routes._(); + static String get api => baseApi(); static String get onlyapi => baseApi(i: 1); @@ -172,4 +174,8 @@ class Route { } static Uri networkInfo() => Uri.parse('$lb/v1/dpip/networkInfo'); + + static String radarTile(String timestamp) { + return 'https://api-1.exptech.dev/api/v1/tiles/radar/$timestamp/{z}/{x}/{y}.png'; + } } diff --git a/lib/app.dart b/lib/app.dart index 6a3b0d24b..247012c34 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,16 +1,19 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/material.dart'; + +import 'package:dynamic_system_colors/dynamic_system_colors.dart'; +import 'package:i18n_extension/i18n_extension.dart'; +import 'package:in_app_update/in_app_update.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/core/notify.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/models/settings/ui.dart'; import 'package:dpip/router.dart'; +import 'package:dpip/utils/constants.dart'; import 'package:dpip/utils/log.dart'; -import 'package:dynamic_system_colors/dynamic_system_colors.dart'; -import 'package:flutter/material.dart'; -import 'package:i18n_extension/i18n_extension.dart'; -import 'package:in_app_update/in_app_update.dart'; -import 'package:provider/provider.dart'; class DpipApp extends StatefulWidget { const DpipApp({super.key}); @@ -86,19 +89,21 @@ class _DpipAppState extends State with WidgetsBindingObserver { colorScheme: model.themeColor == null ? lightDynamic : null, brightness: Brightness.light, snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating), + pageTransitionsTheme: kZoomPageTransitionsTheme, ); final darkTheme = ThemeData( colorSchemeSeed: model.themeColor, colorScheme: model.themeColor == null ? darkDynamic : null, brightness: Brightness.dark, snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating), + pageTransitionsTheme: kZoomPageTransitionsTheme, ); return MaterialApp.router( builder: (context, child) { final mediaQueryData = MediaQuery.of(context); final scale = mediaQueryData.textScaler.clamp(minScaleFactor: 0.5, maxScaleFactor: 1.2); - return MediaQuery(data: MediaQuery.of(context).copyWith(textScaler: scale), child: child!); + return MediaQuery(data: mediaQueryData.copyWith(textScaler: scale), child: child!); }, title: 'DPIP', theme: lightTheme, diff --git a/lib/app/home/_widgets/eew_card.dart b/lib/app/home/_widgets/eew_card.dart index 6c7f8cb2f..138299d40 100644 --- a/lib/app/home/_widgets/eew_card.dart +++ b/lib/app/home/_widgets/eew_card.dart @@ -28,14 +28,16 @@ class EewCard extends StatefulWidget { } class _EewCardState extends State { - late int localIntensity; - late int localArrivalTime; + int? localIntensity; + int? localArrivalTime; int countdown = 0; Timer? _timer; void _updateCountdown() { - final remainingSeconds = ((localArrivalTime - GlobalProviders.data.currentTime) / 1000).floor(); + if (localArrivalTime == null) return; + + final remainingSeconds = ((localArrivalTime! - GlobalProviders.data.currentTime) / 1000).floor(); if (remainingSeconds < -1) return; setState(() => countdown = remainingSeconds); @@ -45,17 +47,19 @@ class _EewCardState extends State { void initState() { super.initState(); - final info = eewLocationInfo( - widget.data.info.magnitude, - widget.data.info.depth, - widget.data.info.latitude, - widget.data.info.longitude, - GlobalProviders.location.coordinateNotifier.value.latitude, - GlobalProviders.location.coordinateNotifier.value.longitude, - ); + if (GlobalProviders.location.coordinates != null) { + final info = eewLocationInfo( + widget.data.info.magnitude, + widget.data.info.depth, + widget.data.info.latitude, + widget.data.info.longitude, + GlobalProviders.location.coordinates!.latitude, + GlobalProviders.location.coordinates!.longitude, + ); - localIntensity = intensityFloatToInt(info.i); - localArrivalTime = (widget.data.info.time + sWaveTimeByDistance(widget.data.info.depth, info.dist)).floor(); + localIntensity = intensityFloatToInt(info.i); + localArrivalTime = (widget.data.info.time + sWaveTimeByDistance(widget.data.info.depth, info.dist)).floor(); + } _updateCountdown(); _timer = Timer.periodic(const Duration(seconds: 1), (_) => _updateCountdown()); @@ -96,7 +100,7 @@ class _EewCardState extends State { children: [ Icon(Symbols.crisis_alert_rounded, color: context.colors.onError, weight: 700, size: 22), Text( - '緊急地震速報'.i18n, + 'EEW'.i18n, style: context.textTheme.labelLarge!.copyWith( color: context.colors.onError, fontWeight: FontWeight.bold, @@ -118,14 +122,23 @@ class _EewCardState extends State { padding: const EdgeInsets.only(top: 8), child: StyledText( text: - '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。' - .i18n - .args({ - 'time': widget.data.info.time.toSimpleDateTimeString(context), - 'location': widget.data.info.location, - 'magnitude': widget.data.info.magnitude.toStringAsFixed(1), - 'intensity': localIntensity.asIntensityLabel, - }), + localIntensity != null + ? '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。' + .i18n + .args({ + 'time': widget.data.info.time.toSimpleDateTimeString(), + 'location': widget.data.info.location, + 'magnitude': widget.data.info.magnitude.toStringAsFixed(1), + 'intensity': localIntensity!.asIntensityLabel, + }) + : '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。' + .i18n + .args({ + 'time': widget.data.info.time.toSimpleDateTimeString(), + 'location': widget.data.info.location, + 'magnitude': widget.data.info.magnitude.toStringAsFixed(1), + 'depth': widget.data.info.depth.toStringAsFixed(1), + }), style: context.textTheme.bodyLarge!.copyWith(color: context.colors.onErrorContainer), tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, ), @@ -133,7 +146,7 @@ class _EewCardState extends State { Selector( selector: (context, model) => model.code, builder: (context, code, child) { - if (code == null) { + if (code == null || localIntensity == null) { return const SizedBox.shrink(); } @@ -160,7 +173,7 @@ class _EewCardState extends State { Padding( padding: const EdgeInsets.only(top: 12, bottom: 8), child: Text( - localIntensity.asIntensityLabel, + localIntensity!.asIntensityLabel, style: context.textTheme.displayMedium!.copyWith( fontWeight: FontWeight.bold, color: context.colors.onErrorContainer, @@ -191,7 +204,7 @@ class _EewCardState extends State { Padding( padding: const EdgeInsets.only(top: 12, bottom: 8), child: - (countdown >= 0) + (countdown > 0) ? RichText( text: TextSpan( children: [ @@ -220,6 +233,7 @@ class _EewCardState extends State { : Text( '抵達'.i18n, style: context.textTheme.displayMedium!.copyWith( + fontSize: context.textTheme.displayMedium!.fontSize! * 0.92, fontWeight: FontWeight.bold, color: context.colors.onErrorContainer, height: 1, diff --git a/lib/app/home/_widgets/history_timeline_item.dart b/lib/app/home/_widgets/history_timeline_item.dart index 377c44ab9..00bdad64a 100644 --- a/lib/app/home/_widgets/history_timeline_item.dart +++ b/lib/app/home/_widgets/history_timeline_item.dart @@ -39,8 +39,7 @@ class HistoryTimelineItem extends StatelessWidget { children: [ Positioned( top: first ? 42 : 0, - bottom: last ? null : 0, - height: last ? 42 : null, + bottom: last ? 0 : 0, width: 1, child: Container(color: context.colors.outlineVariant), ), diff --git a/lib/app/home/_widgets/location_button.dart b/lib/app/home/_widgets/location_button.dart index 8dea39372..fa1664397 100644 --- a/lib/app/home/_widgets/location_button.dart +++ b/lib/app/home/_widgets/location_button.dart @@ -1,12 +1,14 @@ +import 'package:flutter/material.dart'; + +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/app/home/_widgets/blurred_button.dart'; import 'package:dpip/app/settings/location/page.dart'; import 'package:dpip/core/i18n.dart'; import 'package:dpip/global.dart'; import 'package:dpip/models/settings/location.dart'; import 'package:dpip/utils/extensions/build_context.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; class LocationButton extends StatelessWidget { const LocationButton({super.key}); @@ -18,7 +20,12 @@ class LocationButton extends StatelessWidget { builder: (context, code, child) { final location = Global.location[code]; - final content = location == null ? '尚未設定'.i18n : '${location.city} ${location.town}'; + late String content; + if (location == null) { + content = '尚未設定'.i18n; + } else { + content = location.dynamicName; + } return BlurredTextButton( onPressed: () => context.push(SettingsLocationPage.route), diff --git a/lib/app/home/_widgets/radar_card.dart b/lib/app/home/_widgets/radar_card.dart index 20d9d42d0..48d2baad6 100644 --- a/lib/app/home/_widgets/radar_card.dart +++ b/lib/app/home/_widgets/radar_card.dart @@ -3,16 +3,17 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:provider/provider.dart'; import 'package:dpip/api/exptech.dart'; +import 'package:dpip/api/route.dart'; import 'package:dpip/app/map/_lib/utils.dart'; import 'package:dpip/app/map/page.dart'; import 'package:dpip/core/i18n.dart'; -import 'package:dpip/models/settings/ui.dart'; import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/utils/extensions/maplibre.dart'; import 'package:dpip/utils/extensions/string.dart'; import 'package:dpip/utils/log.dart'; +import 'package:dpip/widgets/layout.dart'; import 'package:dpip/widgets/map/map.dart'; typedef PositionUpdateCallback = void Function(); @@ -25,43 +26,48 @@ class RadarMapCard extends StatefulWidget { } class _RadarMapCardState extends State { + late final _key = widget.key ?? UniqueKey(); + late MapLibreMapController mapController; - List radarList = []; + late Future> radarListFuture; - String _getTileUrl(String timestamp) { - return 'https://api-1.exptech.dev/api/v1/tiles/radar/$timestamp/{z}/{x}/{y}.png'; - } + Future _setupMapLayers() async { + final controller = mapController; + + final sourceId = MapSourceIds.radar(); + final layerId = MapLayerIds.radar(); - Future _initializeMap() async { try { - radarList = await ExpTech().getRadarList(); - if (!mounted) return; + final time = (await radarListFuture).last; + final newTileUrl = Routes.radarTile(time); - await _setupRadarLayer(); - if (!mounted) return; - } catch (e) { - TalkerManager.instance.error('RadarMapCard._initializeMap', e); - } - } + if (await controller.exists(sourceId, source: true)) { + await controller.removeSource(sourceId); + } - Future _setupRadarLayer() async { - try { - final newTileUrl = _getTileUrl(radarList.last); + await controller.addSource(sourceId, RasterSourceProperties(tiles: [newTileUrl], tileSize: 256)); - await mapController.addSource('radar-source', RasterSourceProperties(tiles: [newTileUrl], tileSize: 256)); if (!mounted) return; - await mapController.addLayer( - 'radar-source', - 'radar', - const RasterLayerProperties(), - belowLayerId: BaseMapLayerIds.exptechCountyOutline, - ); - } catch (e) { - TalkerManager.instance.error('RadarMapCard._setupRadarLayer', e); + if (!await controller.exists(layerId, layer: true)) { + await controller.addLayer( + sourceId, + layerId, + const RasterLayerProperties(), + belowLayerId: BaseMapLayerIds.exptechCountyOutline, + ); + } + } catch (e, s) { + TalkerManager.instance.error('RadarMapCard._setupMapLayers', e, s); } } + @override + void initState() { + super.initState(); + radarListFuture = ExpTech().getRadarList(); + } + @override Widget build(BuildContext context) { return Stack( @@ -75,42 +81,59 @@ class _RadarMapCardState extends State { ), child: ClipRRect( borderRadius: BorderRadius.circular(16), - child: Column( - mainAxisSize: MainAxisSize.min, + child: Layout.col.min( children: [ SizedBox( height: 200, - child: Selector( - selector: (context, ui) => (themeMode: ui.themeMode, themeColor: ui.themeColor), - builder: (context, data, _) { - final (:themeMode, :themeColor) = data; - - return DpipMap( - key: Key('$themeMode-$themeColor'), - onMapCreated: (controller) => mapController = controller, - onStyleLoadedCallback: () => _initializeMap(), - dragEnabled: false, - rotateGesturesEnabled: false, - zoomGesturesEnabled: false, - ); - }, + child: DpipMap( + key: _key, + onMapCreated: (controller) => mapController = controller, + onStyleLoadedCallback: () => _setupMapLayers(), + dragEnabled: false, + rotateGesturesEnabled: false, + zoomGesturesEnabled: false, + focusUserLocationWhenUpdated: true, ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: Layout.row.between( children: [ - Row( - spacing: 8, + Layout.row[8]( children: [ const Icon(Symbols.radar, size: 24), Text('雷達回波'.i18n, style: context.textTheme.titleMedium), - if (radarList.isNotEmpty) - Text( - radarList.last.toLocaleTimeString(context), - style: context.textTheme.bodySmall?.copyWith(color: context.colors.onSurfaceVariant), - ), + FutureBuilder( + future: radarListFuture, + builder: (context, snapshot) { + final data = snapshot.data; + + if (data == null) return const SizedBox.shrink(); + + final style = context.textTheme.labelSmall?.copyWith( + color: context.colors.onSurfaceVariant, + ); + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: context.colors.surfaceContainer, + border: Border.all(color: context.colors.outlineVariant), + borderRadius: BorderRadius.circular(16), + ), + child: Layout.row[4]( + children: [ + Icon( + Symbols.schedule_rounded, + size: (style?.fontSize ?? 12) * 1.25, + color: context.colors.onSurfaceVariant, + ), + Text(data.last.toSimpleDateTimeString(), style: style), + ], + ), + ); + }, + ), ], ), const Icon(Symbols.chevron_right_rounded, size: 24), @@ -124,7 +147,7 @@ class _RadarMapCardState extends State { ), Positioned.fill( child: Material( - color: Colors.transparent, + type: MaterialType.transparency, child: InkWell( onTap: () => context.push(MapPage.route(options: MapPageOptions(initialLayers: {MapLayer.radar}))), borderRadius: BorderRadius.circular(16), @@ -134,10 +157,4 @@ class _RadarMapCardState extends State { ], ); } - - @override - void dispose() { - mapController.dispose(); - super.dispose(); - } } diff --git a/lib/app/home/_widgets/thunderstorm_card.dart b/lib/app/home/_widgets/thunderstorm_card.dart index b705d7367..d9f2e34cc 100644 --- a/lib/app/home/_widgets/thunderstorm_card.dart +++ b/lib/app/home/_widgets/thunderstorm_card.dart @@ -74,7 +74,7 @@ class ThunderstormCard extends StatelessWidget { padding: const EdgeInsets.only(top: 8), child: StyledText( text: '您所在區域附近有劇烈雷雨或降雨發生,請注意防範,持續至 {time} 。'.i18n.args({ - 'time': history.time.expiresAt.toSimpleDateTimeString(context), + 'time': history.time.expiresAt.toSimpleDateTimeString(), }), style: context.textTheme.bodyLarge!.copyWith(color: context.theme.extendedColors.onBlueContainer), tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, diff --git a/lib/app/home/_widgets/weather_header.dart b/lib/app/home/_widgets/weather_header.dart index 1aa6bd155..b5e1eee95 100644 --- a/lib/app/home/_widgets/weather_header.dart +++ b/lib/app/home/_widgets/weather_header.dart @@ -193,7 +193,7 @@ class WeatherHeader extends StatelessWidget { children: [ Icon(Symbols.pin_drop_rounded, size: 16, color: context.colors.onSurfaceVariant), Text( - weather.weather.station.name, + weather.weather.id.weatherStation, style: context.theme.textTheme.bodyLarge!.copyWith(color: context.colors.onSurfaceVariant), ), ], diff --git a/lib/app/home/page.dart b/lib/app/home/page.dart index 402982f1e..c7da379ab 100644 --- a/lib/app/home/page.dart +++ b/lib/app/home/page.dart @@ -39,6 +39,7 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { final _refreshIndicatorKey = GlobalKey(); + Key? _mapKey; bool _isLoading = false; bool _isOutOfService = false; @@ -63,18 +64,23 @@ class _HomePageState extends State { if (_isLoading) return; final auto = GlobalProviders.location.auto; - final code = GlobalProviders.location.codeNotifier.value; + final code = GlobalProviders.location.code; final location = Global.location[code]; if (code == null || location == null) { if (auto) { setState(() => _isOutOfService = true); } + setState(() => _weather = _history = null); return; } - setState(() => _isLoading = true); + setState(() { + _isLoading = true; + _mapKey = Key('${DateTime.now().millisecondsSinceEpoch}'); + }); + _refreshIndicatorKey.currentState?.show(); try { @@ -123,13 +129,14 @@ class _HomePageState extends State { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => _checkVersion()); - GlobalProviders.location.codeNotifier.addListener(_refresh); + GlobalProviders.location.$code.addListener(_refresh); _refresh(); } @override Widget build(BuildContext context) { final topPadding = 24 + 48 + context.padding.top; + return Stack( children: [ RefreshIndicator( @@ -165,7 +172,7 @@ class _HomePageState extends State { Padding(padding: const EdgeInsets.all(16), child: ThunderstormCard(_thunderstorm!)), // 地圖 - const Padding(padding: EdgeInsets.all(16), child: RadarMapCard()), + Padding(padding: const EdgeInsets.all(16), child: RadarMapCard(key: _mapKey)), // 歷史資訊 Builder( @@ -182,7 +189,7 @@ class _HomePageState extends State { children: grouped.entries.sorted((a, b) => b.key.compareTo(a.key)).mapIndexed((index, entry) { final date = entry.key; - final historyGroup = entry.value; + final historyGroup = entry.value.sorted((a, b) => b.time.send.compareTo(a.time.send)); return Column( children: [ DateTimelineItem(date, first: index == 0), @@ -205,7 +212,6 @@ class _HomePageState extends State { ], ), ), - const Positioned( top: 24, left: 0, @@ -218,7 +224,7 @@ class _HomePageState extends State { @override void dispose() { - GlobalProviders.location.codeNotifier.removeListener(_refresh); + GlobalProviders.location.$code.removeListener(_refresh); super.dispose(); } } diff --git a/lib/app/map/_lib/managers/monitor.dart b/lib/app/map/_lib/managers/monitor.dart index 7b716f276..b3357352e 100644 --- a/lib/app/map/_lib/managers/monitor.dart +++ b/lib/app/map/_lib/managers/monitor.dart @@ -1,6 +1,14 @@ import 'dart:async'; import 'dart:collection'; +import 'package:flutter/material.dart'; + +import 'package:i18n_extension/i18n_extension.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; +import 'package:styled_text/styled_text.dart'; + import 'package:dpip/api/model/eew.dart'; import 'package:dpip/app/map/_lib/manager.dart'; import 'package:dpip/app/map/_lib/utils.dart'; @@ -17,12 +25,6 @@ import 'package:dpip/utils/instrumental_intensity_color.dart'; import 'package:dpip/utils/log.dart'; import 'package:dpip/widgets/map/map.dart'; import 'package:dpip/widgets/sheet/morphing_sheet.dart'; -import 'package:flutter/material.dart'; -import 'package:i18n_extension/i18n_extension.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; -import 'package:styled_text/styled_text.dart'; class MonitorMapLayerManager extends MapLayerManager { final bool isReplayMode; @@ -34,7 +36,7 @@ class MonitorMapLayerManager extends MapLayerManager { super.context, super.controller, { this.isReplayMode = false, - this.replayTimestamp = 0, //1751918230855, + this.replayTimestamp = 0, //1756300288424, }) { if (isReplayMode) { GlobalProviders.data.setReplayMode(true, replayTimestamp); @@ -108,11 +110,10 @@ class MonitorMapLayerManager extends MapLayerManager { Future _focus() async { try { - final location = GlobalProviders.location.coordinateNotifier.value; + final location = GlobalProviders.location.coordinates; - if (location.isValid) { + if (location != null && location.isValid) { await controller.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); - TalkerManager.instance.info('Moved Camera to $location'); } else { await controller.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); TalkerManager.instance.info('Moved Camera to ${DpipMap.kTaiwanCenter}'); @@ -126,6 +127,8 @@ class MonitorMapLayerManager extends MapLayerManager { Future setup() async { if (didSetup) return; + final colors = context.colors; + try { final sources = await controller.getSourceIds(); final layers = await controller.getLayerIds(); @@ -143,7 +146,6 @@ class MonitorMapLayerManager extends MapLayerManager { final pWaveLayerId = MapLayerIds.eew('p'); final sWaveLayerId = MapLayerIds.eew('s'); - // 检查所有源和图层是否存在 final isRtsSourceExists = sources.contains(rtsSourceId); final isRtsLayerExists = layers.contains(rtsLayerId); final isIntensitySourceExists = sources.contains(intensitySourceId); @@ -158,7 +160,6 @@ class MonitorMapLayerManager extends MapLayerManager { if (!context.mounted) return; - // 按顺序添加所有数据源 if (!isRtsSourceExists) { final data = GlobalProviders.data.getRtsGeoJson(); await controller.addSource(rtsSourceId, GeojsonSourceProperties(data: data)); @@ -191,8 +192,6 @@ class MonitorMapLayerManager extends MapLayerManager { if (!context.mounted) return; - // 按顺序从下到上添加图层 - // 1. RTS 图层(最底层) if (!isRtsLayerExists) { final properties = CircleLayerProperties( circleColor: kRtsCircleColor, @@ -212,12 +211,109 @@ class MonitorMapLayerManager extends MapLayerManager { ], visibility: visible ? 'visible' : 'none', ); + final properties2 = SymbolLayerProperties( + textField: [ + Expressions.format, + [Expressions.get, 'id'], + { + 'text-font': [ + Expressions.literal, + ['Noto Sans TC Bold'], + ], + }, + '\n', + {}, + [ + Expressions.caseExpression, + [ + Expressions.all, + [Expressions.has, 'city'], + [Expressions.has, 'town'], + ], + [ + Expressions.concat, + [Expressions.get, 'city'], + ' ', + [Expressions.get, 'town'], + ], + '海外測站'.i18n, + ], + { + 'text-font': [ + Expressions.literal, + ['Noto Sans TC Bold'], + ], + }, + '\n', + {}, + [ + Expressions.caseExpression, + [ + Expressions.all, + [Expressions.has, 'i'], + [Expressions.has, 'pga'], + [Expressions.has, 'pgv'], + ], + [ + Expressions.concat, + [ + Expressions.concat, + '即時震度:'.i18n, + [Expressions.get, 'i'], + ], + '\n', + [ + Expressions.concat, + '地動加速度:'.i18n, + [Expressions.get, 'pga'], + 'gal', + ], + '\n', + [ + Expressions.concat, + '地動速度:'.i18n, + [Expressions.get, 'pgv'], + 'cm/s', + ], + ], + '無資料'.i18n, + ], + {}, + ], + textSize: 10, + textColor: colors.onSurfaceVariant.toHexStringRGB(), + textHaloColor: colors.outlineVariant.toHexStringRGB(), + textHaloWidth: 1, + textFont: ['Noto Sans TC Regular'], + textRadialOffset: 1.5, + textAnchor: 'top', + textJustify: 'auto', + textVariableAnchor: [ + 'top', + 'bottom', + 'left', + 'right', + 'top-left', + 'bottom-left', + 'top-right', + 'bottom-right', + ], + visibility: visible ? 'visible' : 'none', + ); await controller.addLayer(rtsSourceId, rtsLayerId, properties, belowLayerId: BaseMapLayerIds.userLocation); TalkerManager.instance.info('Added Layer "$rtsLayerId"'); + + await controller.addLayer( + rtsSourceId, + '$rtsLayerId-label', + properties2, + belowLayerId: BaseMapLayerIds.userLocation, + minzoom: 10, + ); + TalkerManager.instance.info('Added Layer "$rtsLayerId-label"'); } - // 2. Intensity0 图层 if (!isIntensity0LayerExists) { final properties = CircleLayerProperties( circleColor: Colors.grey.toHexStringRGB(), @@ -257,20 +353,11 @@ class MonitorMapLayerManager extends MapLayerManager { TalkerManager.instance.info('Added Layer "$intensity0LayerId"'); } - // 3. Intensity 图层 if (!isIntensityLayerExists) { const properties = SymbolLayerProperties( symbolSortKey: [Expressions.get, 'intensity'], symbolZOrder: 'source', - iconSize: [ - Expressions.interpolate, - ['linear'], - [Expressions.zoom], - 5, - 0.2, - 10, - 0.8, - ], + iconSize: kSymbolIconSize, iconImage: [ Expressions.match, [Expressions.get, 'intensity'], @@ -308,9 +395,8 @@ class MonitorMapLayerManager extends MapLayerManager { TalkerManager.instance.info('Added Layer "$intensityLayerId"'); } - // 4. Box 图层 if (!isBoxLayerExists) { - final properties = LineLayerProperties( + const properties = LineLayerProperties( lineWidth: 2, lineColor: [ Expressions.match, @@ -342,14 +428,13 @@ class MonitorMapLayerManager extends MapLayerManager { TalkerManager.instance.info('Added Layer "$boxLayerId"'); } - // 5. EEW 图层(P波、S波、震央标记) if (!isEewLayerExists) { - // 5.1 P波圈 final pWaveProperties = LineLayerProperties( lineColor: Colors.cyan.toHexStringRGB(), lineWidth: 2, visibility: visible ? 'visible' : 'none', ); + await controller.addLayer( eewSourceId, pWaveLayerId, @@ -364,12 +449,12 @@ class MonitorMapLayerManager extends MapLayerManager { ); TalkerManager.instance.info('Added Layer "$pWaveLayerId"'); - // 5.2 S波圈 final sWaveProperties = LineLayerProperties( lineColor: Colors.red.toHexStringRGB(), lineWidth: 2, visibility: visible ? 'visible' : 'none', ); + await controller.addLayer( eewSourceId, sWaveLayerId, @@ -384,7 +469,6 @@ class MonitorMapLayerManager extends MapLayerManager { ); TalkerManager.instance.info('Added Layer "$sWaveLayerId"'); - // 5.3 震央标记(最顶层) final epicenterProperties = SymbolLayerProperties( iconImage: 'cross-7', iconSize: kSymbolIconSize, @@ -393,6 +477,7 @@ class MonitorMapLayerManager extends MapLayerManager { symbolZOrder: 'source', visibility: visible ? 'visible' : 'none', ); + await controller.addLayer( eewSourceId, epicenterLayerId, @@ -447,6 +532,7 @@ class MonitorMapLayerManager extends MapLayerManager { final hasBox = GlobalProviders.data.rts?.box.isNotEmpty ?? false; await controller.setLayerVisibility(rtsLayerId, !hasBox); + await controller.setLayerVisibility('$rtsLayerId-label', !hasBox); await controller.setLayerVisibility(intensityLayerId, hasBox); await controller.setLayerVisibility(intensity0LayerId, hasBox); await controller.setLayerVisibility(boxLayerId, hasBox); @@ -532,23 +618,17 @@ class MonitorMapLayerManager extends MapLayerManager { // rts await controller.setLayerVisibility(rtsLayerId, false); - TalkerManager.instance.info('Hiding Layer "$rtsLayerId"'); + await controller.setLayerVisibility('$rtsLayerId-label', false); // intensity await controller.setLayerVisibility(intensityLayerId, false); - TalkerManager.instance.info('Hiding Layer "$intensityLayerId"'); await controller.setLayerVisibility(intensity0LayerId, false); - TalkerManager.instance.info('Hiding Layer "$intensity0LayerId"'); await controller.setLayerVisibility(boxLayerId, false); - TalkerManager.instance.info('Hiding Layer "$boxLayerId"'); // eew await controller.setLayerVisibility(epicenterLayerId, false); - TalkerManager.instance.info('Hiding Layer "$epicenterLayerId"'); await controller.setLayerVisibility(pWaveLayerId, false); - TalkerManager.instance.info('Hiding Layer "$pWaveLayerId"'); await controller.setLayerVisibility(sWaveLayerId, false); - TalkerManager.instance.info('Hiding Layer "$sWaveLayerId"'); visible = false; } catch (e, s) { @@ -575,21 +655,15 @@ class MonitorMapLayerManager extends MapLayerManager { final hasBox = GlobalProviders.data.rts?.box.isNotEmpty ?? false; await controller.setLayerVisibility(rtsLayerId, !hasBox); - TalkerManager.instance.info('Showing Layer "$rtsLayerId"'); + await controller.setLayerVisibility('$rtsLayerId-label', !hasBox); await controller.setLayerVisibility(intensityLayerId, hasBox); - TalkerManager.instance.info('Showing Layer "$intensityLayerId"'); await controller.setLayerVisibility(intensity0LayerId, hasBox); - TalkerManager.instance.info('Showing Layer "$intensity0LayerId"'); await controller.setLayerVisibility(boxLayerId, hasBox); - TalkerManager.instance.info('Showing Layer "$boxLayerId"'); await controller.setLayerVisibility(epicenterLayerId, true); - TalkerManager.instance.info('Showing Layer "$epicenterLayerId"'); await controller.setLayerVisibility(pWaveLayerId, true); - TalkerManager.instance.info('Showing Layer "$pWaveLayerId"'); await controller.setLayerVisibility(sWaveLayerId, true); - TalkerManager.instance.info('Showing Layer "$sWaveLayerId"'); await _focus(); @@ -619,6 +693,8 @@ class MonitorMapLayerManager extends MapLayerManager { // rts await controller.removeLayer(rtsLayerId); TalkerManager.instance.info('Removed Layer "$rtsLayerId"'); + await controller.removeLayer('$rtsLayerId-label'); + TalkerManager.instance.info('Removed Layer "$rtsLayerId-label"'); await controller.removeSource(rtsSourceId); TalkerManager.instance.info('Removed Source "$rtsSourceId"'); @@ -717,221 +793,420 @@ class _MonitorMapLayerSheetState extends State { } else { final data = activeEew.first; - final info = eewLocationInfo( - data.info.magnitude, - data.info.depth, - data.info.latitude, - data.info.longitude, - GlobalProviders.location.coordinateNotifier.value.latitude, - GlobalProviders.location.coordinateNotifier.value.longitude, - ); - - localIntensity = intensityFloatToInt(info.i); - localArrivalTime = (data.info.time + sWaveTimeByDistance(data.info.depth, info.dist)).floor(); - - _timer = Timer.periodic(const Duration(seconds: 1), (_) => _updateCountdown()); - - return InkWell( - onTap: () => _toggleCollapse(), - child: Padding( - padding: const EdgeInsets.all(12), - child: - _isCollapsed - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, + if (GlobalProviders.location.coordinates == null) { + if (_isCollapsed) { + child = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 8, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - spacing: 8, - children: [ - Container( - decoration: BoxDecoration( - color: context.colors.error, - borderRadius: BorderRadius.circular(8), - ), - padding: - activeEew.length > 1 - ? const EdgeInsets.fromLTRB(8, 6, 12, 6) - : const EdgeInsets.fromLTRB(8, 6, 8, 6), - child: Row( - mainAxisSize: MainAxisSize.min, - spacing: 4, + Container( + decoration: BoxDecoration( + color: context.colors.error, + borderRadius: BorderRadius.circular(8), + ), + padding: + activeEew.length > 1 + ? const EdgeInsets.fromLTRB(8, 6, 12, 6) + : const EdgeInsets.fromLTRB(8, 6, 8, 6), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + Icon( + Symbols.crisis_alert_rounded, + color: context.colors.onError, + weight: 700, + size: 16, + ), + if (activeEew.length > 1) + RichText( + text: TextSpan( children: [ - Icon( - Symbols.crisis_alert_rounded, - color: context.colors.onError, - weight: 700, - size: 16, + TextSpan( + text: '1', + style: context.textTheme.labelMedium!.copyWith( + color: context.colors.onError, + fontWeight: FontWeight.bold, + ), ), - if (activeEew.length > 1) - RichText( - text: TextSpan( - children: [ - TextSpan( - text: '1', - style: context.textTheme.labelMedium!.copyWith( - color: context.colors.onError, - fontWeight: FontWeight.bold, - ), - ), - TextSpan( - text: '/${activeEew.length}', - style: context.textTheme.labelMedium!.copyWith( - color: context.colors.onError.withValues(alpha: 0.6), - fontWeight: FontWeight.bold, - ), - ), - ], - ), + TextSpan( + text: '/${activeEew.length}', + style: context.textTheme.labelMedium!.copyWith( + color: context.colors.onError.withValues(alpha: 0.6), + fontWeight: FontWeight.bold, ), + ), ], ), ), - Text( - '#${data.serial} ${data.info.time.toSimpleDateTimeString(context)} ${data.info.location}', - style: context.textTheme.bodyMedium!.copyWith( - fontWeight: FontWeight.bold, - color: context.colors.onErrorContainer, - ), - ), - ], - ), - Icon(Symbols.expand_less_rounded, color: context.colors.onErrorContainer, size: 24 - ), - ], + ], + ), ), - Padding( - padding: const EdgeInsets.only(top: 8), + Text( + '#${data.serial} ${data.info.time.toSimpleDateTimeString()} ${data.info.location}', + style: context.textTheme.bodyMedium!.copyWith( + fontWeight: FontWeight.bold, + color: context.colors.onErrorContainer, + ), + ), + ], + ), + Icon(Symbols.expand_less_rounded, color: context.colors.onErrorContainer, size: 24), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: StyledText( + text: '規模 M{magnitude},深度{depth}公里'.i18n.args({ + 'magnitude': data.info.magnitude.toStringAsFixed(1), + 'depth': data.info.depth.toStringAsFixed(1), + }), + style: context.textTheme.bodyMedium!.copyWith(color: context.colors.onErrorContainer), + tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, + ), + ), + ], + ); + } else { + child = Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 8, + children: [ + Container( + decoration: BoxDecoration( + color: context.colors.error, + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.fromLTRB(8, 6, 12, 6), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + spacing: 4, children: [ - StyledText( - text: '規模 M{magnitude},所在地預估{intensity}'.i18n.args({ - 'time': data.info.time.toSimpleDateTimeString(context), - 'location': data.info.location, - 'magnitude': data.info.magnitude.toStringAsFixed(1), - 'intensity': localIntensity.asIntensityLabel, - }), - style: context.textTheme.bodyMedium!.copyWith( - color: context.colors.onErrorContainer, - ), - tags: { - 'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold)), - }, + Icon( + Symbols.crisis_alert_rounded, + color: context.colors.onError, + weight: 700, + size: 22, ), - Text( - countdown >= 0 - ? '{countdown}秒後抵達'.i18n.args({'countdown': countdown}) - : '已抵達'.i18n, - style: context.textTheme.bodyMedium!.copyWith( + 'EEW'.i18n, + style: context.textTheme.labelLarge!.copyWith( + color: context.colors.onError, fontWeight: FontWeight.bold, - color: context.colors.onErrorContainer, - height: 1, - leadingDistribution: TextLeadingDistribution.even, ), ), ], ), ), + Text( + '第 {serial} 報'.i18n.args({'serial': activeEew.first.serial}), + style: context.textTheme.bodyLarge!.copyWith( + color: context.colors.onErrorContainer, + ), + ), ], - ) - : Column( - mainAxisSize: MainAxisSize.min, + ), + Icon(Symbols.expand_more_rounded, color: context.colors.onErrorContainer, size: 24), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: StyledText( + text: + '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、深度{depth}公里。' + .i18n + .args({ + 'time': data.info.time.toSimpleDateTimeString(), + 'location': data.info.location, + 'magnitude': data.info.magnitude.toStringAsFixed(1), + 'depth': data.info.depth.toStringAsFixed(1), + }), + style: context.textTheme.bodyLarge!.copyWith(color: context.colors.onErrorContainer), + tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, + ), + ), + ], + ); + } + } else { + final info = eewLocationInfo( + data.info.magnitude, + data.info.depth, + data.info.latitude, + data.info.longitude, + GlobalProviders.location.coordinates!.latitude, + GlobalProviders.location.coordinates!.longitude, + ); + + localIntensity = intensityFloatToInt(info.i); + localArrivalTime = (data.info.time + sWaveTimeByDistance(data.info.depth, info.dist)).floor(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + _updateCountdown(); + }); + _timer ??= Timer.periodic(const Duration(seconds: 1), (_) => _updateCountdown()); + + if (_isCollapsed) { + child = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 8, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - spacing: 8, - children: [ - Container( - decoration: BoxDecoration( - color: context.colors.error, - borderRadius: BorderRadius.circular(8), - ), - padding: const EdgeInsets.fromLTRB(8, 6, 12, 6), - child: Row( - mainAxisSize: MainAxisSize.min, - spacing: 4, + Container( + decoration: BoxDecoration( + color: context.colors.error, + borderRadius: BorderRadius.circular(8), + ), + padding: + activeEew.length > 1 + ? const EdgeInsets.fromLTRB(8, 6, 12, 6) + : const EdgeInsets.fromLTRB(8, 6, 8, 6), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + Icon( + Symbols.crisis_alert_rounded, + color: context.colors.onError, + weight: 700, + size: 16, + ), + if (activeEew.length > 1) + RichText( + text: TextSpan( children: [ - Icon( - Symbols.crisis_alert_rounded, - color: context.colors.onError, - weight: 700, - size: 22, - ), - Text( - '緊急地震速報'.i18n, - style: context.textTheme.labelLarge!.copyWith( + TextSpan( + text: '1', + style: context.textTheme.labelMedium!.copyWith( color: context.colors.onError, fontWeight: FontWeight.bold, ), ), + TextSpan( + text: '/${activeEew.length}', + style: context.textTheme.labelMedium!.copyWith( + color: context.colors.onError.withValues(alpha: 0.6), + fontWeight: FontWeight.bold, + ), + ), ], ), ), - Text( - '第 {serial} 報'.i18n.args({'serial': activeEew.first.serial}), - style: context.textTheme.bodyLarge!.copyWith( - color: context.colors.onErrorContainer, - ), + ], + ), + ), + Text( + '#${data.serial} ${data.info.time.toSimpleDateTimeString()} ${data.info.location}', + style: context.textTheme.bodyMedium!.copyWith( + fontWeight: FontWeight.bold, + color: context.colors.onErrorContainer, + ), + ), + ], + ), + Icon(Symbols.expand_less_rounded, color: context.colors.onErrorContainer, size: 24), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + StyledText( + text: '規模 M{magnitude},所在地預估{intensity}'.i18n.args({ + 'magnitude': data.info.magnitude.toStringAsFixed(1), + 'intensity': localIntensity.asIntensityLabel, + }), + style: context.textTheme.bodyMedium!.copyWith(color: context.colors.onErrorContainer), + tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, + ), + + Text( + countdown > 0 ? '{countdown}秒後抵達'.i18n.args({'countdown': countdown}) : '已抵達'.i18n, + style: context.textTheme.bodyMedium!.copyWith( + fontWeight: FontWeight.bold, + color: context.colors.onErrorContainer, + height: 1, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + ], + ), + ), + ], + ); + } else { + child = Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + spacing: 8, + children: [ + Container( + decoration: BoxDecoration( + color: context.colors.error, + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.fromLTRB(8, 6, 12, 6), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + Icon( + Symbols.crisis_alert_rounded, + color: context.colors.onError, + weight: 700, + size: 22, + ), + Text( + 'EEW'.i18n, + style: context.textTheme.labelLarge!.copyWith( + color: context.colors.onError, + fontWeight: FontWeight.bold, ), - ], - ), - Icon(Symbols.expand_more_rounded, color: context.colors.onErrorContainer, size: 24), - ], + ), + ], + ), ), - Padding( - padding: const EdgeInsets.only(top: 8), - child: StyledText( - text: - '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。' - .i18n - .args({ - 'time': data.info.time.toSimpleDateTimeString(context), - 'location': data.info.location, - 'magnitude': data.info.magnitude.toStringAsFixed(1), - 'intensity': localIntensity.asIntensityLabel, - }), - style: context.textTheme.bodyLarge!.copyWith(color: context.colors.onErrorContainer), - tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, + Text( + '第 {serial} 報'.i18n.args({'serial': activeEew.first.serial}), + style: context.textTheme.bodyLarge!.copyWith( + color: context.colors.onErrorContainer, ), ), - Selector( - selector: (context, model) => model.code, - builder: (context, code, child) { - if (code == null) { - return const SizedBox.shrink(); - } - - return Padding( - padding: const EdgeInsets.only(top: 8, bottom: 4), - child: IntrinsicHeight( - child: Row( + ], + ), + Icon(Symbols.expand_more_rounded, color: context.colors.onErrorContainer, size: 24), + ], + ), + Padding( + padding: const EdgeInsets.only(top: 8), + child: StyledText( + text: + '{time} 左右,{location}附近發生有感地震,預估規模 M{magnitude}、所在地最大震度{intensity}。' + .i18n + .args({ + 'time': data.info.time.toSimpleDateTimeString(), + 'location': data.info.location, + 'magnitude': data.info.magnitude.toStringAsFixed(1), + 'intensity': localIntensity.asIntensityLabel, + }), + style: context.textTheme.bodyLarge!.copyWith(color: context.colors.onErrorContainer), + tags: {'bold': StyledTextTag(style: const TextStyle(fontWeight: FontWeight.bold))}, + ), + ), + Selector( + selector: (context, model) => model.code, + builder: (context, code, child) { + if (code == null) { + return const SizedBox.shrink(); + } + + return Padding( + padding: const EdgeInsets.only(top: 8, bottom: 4), + child: IntrinsicHeight( + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - '所在地預估'.i18n, - style: context.textTheme.labelLarge!.copyWith( - color: context.colors.onErrorContainer.withValues(alpha: 0.6), - ), - ), - Padding( - padding: const EdgeInsets.only(top: 12, bottom: 8), - child: Text( - localIntensity.asIntensityLabel, + Text( + '所在地預估'.i18n, + style: context.textTheme.labelLarge!.copyWith( + color: context.colors.onErrorContainer.withValues(alpha: 0.6), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 12, bottom: 8), + child: Text( + localIntensity.asIntensityLabel, + style: context.textTheme.displayMedium!.copyWith( + fontWeight: FontWeight.bold, + color: context.colors.onErrorContainer, + height: 1, + leadingDistribution: TextLeadingDistribution.even, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ), + VerticalDivider( + color: context.colors.onErrorContainer.withValues(alpha: 0.4), + width: 24, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + '震波'.i18n, + style: context.textTheme.labelLarge!.copyWith( + color: context.colors.onErrorContainer.withValues(alpha: 0.6), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 12, bottom: 8), + child: + (countdown > 0) + ? RichText( + text: TextSpan( + children: [ + TextSpan( + text: countdown.toString(), + style: TextStyle( + fontSize: + context.textTheme.displayMedium!.fontSize! * 1.15, + ), + ), + TextSpan( + text: ' 秒'.i18n, + style: TextStyle( + fontSize: context.textTheme.labelLarge!.fontSize, + ), + ), + ], + style: context.textTheme.displayMedium!.copyWith( + fontWeight: FontWeight.bold, + color: context.colors.onErrorContainer, + height: 1, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + textAlign: TextAlign.center, + ) + : Text( + '抵達'.i18n, style: context.textTheme.displayMedium!.copyWith( + fontSize: context.textTheme.displayMedium!.fontSize! * 0.81, fontWeight: FontWeight.bold, color: context.colors.onErrorContainer, height: 1, @@ -939,83 +1214,25 @@ class _MonitorMapLayerSheetState extends State { ), textAlign: TextAlign.center, ), - ), - ], - ), - ), - ), - VerticalDivider( - color: context.colors.onErrorContainer.withValues(alpha: 0.4), - width: 24, - ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - '震波'.i18n, - style: context.textTheme.labelLarge!.copyWith( - color: context.colors.onErrorContainer.withValues(alpha: 0.6), - ), - ), - Padding( - padding: const EdgeInsets.only(top: 12, bottom: 8), - child: - (countdown >= 0) - ? RichText( - text: TextSpan( - children: [ - TextSpan( - text: countdown.toString(), - style: TextStyle( - fontSize: - context.textTheme.displayMedium!.fontSize! * - 1.15, - ), - ), - TextSpan( - text: ' 秒'.i18n, - style: TextStyle( - fontSize: context.textTheme.labelLarge!.fontSize, - ), - ), - ], - style: context.textTheme.displayMedium!.copyWith( - fontWeight: FontWeight.bold, - color: context.colors.onErrorContainer, - height: 1, - leadingDistribution: TextLeadingDistribution.even, - ), - ), - textAlign: TextAlign.center, - ) - : Text( - '抵達'.i18n, - style: context.textTheme.displayMedium!.copyWith( - fontWeight: FontWeight.bold, - color: context.colors.onErrorContainer, - height: 1, - leadingDistribution: TextLeadingDistribution.even, - ), - textAlign: TextAlign.center, - ), - ), - ], - ), - ), ), ], ), ), - ); - }, + ), + ], ), - ], - ), - ), + ), + ); + }, + ), + ], + ); + } + } + + return InkWell( + onTap: () => _toggleCollapse(), + child: Padding(padding: const EdgeInsets.all(12), child: child), ); } }, @@ -1036,15 +1253,15 @@ class _MonitorMapLayerSheetState extends State { } return Container( padding: const EdgeInsets.all(8), - width: 200, + width: 230, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface.withAlpha((0.5 * 255).round()), + color: context.colors.surface.withValues(alpha: 0.5), borderRadius: BorderRadius.circular(16), ), child: Text( displayTime, textAlign: TextAlign.center, - style: TextStyle(color: Theme.of(context).colorScheme.onSurface, fontSize: 16), + style: TextStyle(color: context.colors.onSurface, fontSize: 16), ), ); }, diff --git a/lib/app/map/_lib/managers/precipitation.dart b/lib/app/map/_lib/managers/precipitation.dart index ad279882f..b4eaaeaa8 100644 --- a/lib/app/map/_lib/managers/precipitation.dart +++ b/lib/app/map/_lib/managers/precipitation.dart @@ -1,23 +1,28 @@ +import 'package:flutter/material.dart'; + import 'package:collection/collection.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/api/exptech.dart'; import 'package:dpip/api/model/weather/rain.dart'; import 'package:dpip/app/map/_lib/manager.dart'; import 'package:dpip/app/map/_lib/utils.dart'; +import 'package:dpip/app/map/_widgets/map_legend.dart'; import 'package:dpip/core/i18n.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/models/data.dart'; +import 'package:dpip/utils/constants.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/extensions/string.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/log.dart'; +import 'package:dpip/widgets/blurred_container.dart'; import 'package:dpip/widgets/map/map.dart'; import 'package:dpip/widgets/sheet/morphing_sheet.dart'; import 'package:dpip/widgets/ui/loading_icon.dart'; -import 'package:flutter/material.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; class RainData { final double latitude; @@ -48,6 +53,8 @@ class PrecipitationMapLayerManager extends MapLayerManager { final currentPrecipitationInterval = ValueNotifier('now'); final isLoading = ValueNotifier(false); + DateTime? _lastFetchTime; + Function(String)? onTimeChanged; Future setPrecipitationTime(String time) async { @@ -61,8 +68,6 @@ class PrecipitationMapLayerManager extends MapLayerManager { await setup(); onTimeChanged?.call(time); - - TalkerManager.instance.info('Updated Precipitation data to "$time"'); } catch (e, s) { TalkerManager.instance.error('PrecipitationMapLayerManager.setPrecipitationTime', e, s); } finally { @@ -79,10 +84,10 @@ class PrecipitationMapLayerManager extends MapLayerManager { final hideLayerId = '$layerId-${currentPrecipitationInterval.value}'; await controller.setLayerVisibility(showLayerId, true); - TalkerManager.instance.info('Showing Layer "$showLayerId"'); + await controller.setLayerVisibility('$showLayerId-label', true); await controller.setLayerVisibility(hideLayerId, false); - TalkerManager.instance.info('Hiding Layer "$hideLayerId"'); + await controller.setLayerVisibility('$hideLayerId-label', false); currentPrecipitationInterval.value = interval; } catch (e, s) { @@ -92,11 +97,10 @@ class PrecipitationMapLayerManager extends MapLayerManager { Future _focus() async { try { - final location = GlobalProviders.location.coordinateNotifier.value; + final location = GlobalProviders.location.coordinates; - if (location.isValid) { + if (location != null && location.isValid) { await controller.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); - TalkerManager.instance.info('Moved Camera to $location'); } else { await controller.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); TalkerManager.instance.info('Moved Camera to ${DpipMap.kTaiwanCenter}'); @@ -106,17 +110,28 @@ class PrecipitationMapLayerManager extends MapLayerManager { } } + Future _fetchData() async { + try { + final precipitationList = (await ExpTech().getRainList()).reversed.toList(); + if (!context.mounted) return; + + GlobalProviders.data.setPrecipitation(precipitationList); + currentPrecipitationTime.value ??= precipitationList.first; + _lastFetchTime = DateTime.now(); + } catch (e, s) { + TalkerManager.instance.error('PrecipitationMapLayerManager._fetchData', e, s); + } + } + @override Future setup() async { if (didSetup) return; + final colors = context.colors; + try { if (GlobalProviders.data.precipitation.isEmpty) { - final precipitationList = (await ExpTech().getRainList()).reversed.toList(); - if (!context.mounted) return; - - GlobalProviders.data.setPrecipitation(precipitationList); - currentPrecipitationTime.value = precipitationList.first; + await _fetchData(); } final time = currentPrecipitationTime.value; @@ -146,83 +161,88 @@ class PrecipitationMapLayerManager extends MapLayerManager { final properties = GeojsonSourceProperties(data: data); await controller.addSource(sourceId, properties); - TalkerManager.instance.info('Added Source "$sourceId"'); if (!context.mounted) return; } if (!isLayerExists) { - final properties = { + final Map properties = { for (final interval in precipitationIntervals) - interval: CircleLayerProperties( - circleRadius: [ - Expressions.interpolate, - ['linear'], - [Expressions.zoom], - 7, - 5, - 12, - 15, - ], - circleColor: [ - Expressions.interpolate, - ['linear'], - [Expressions.get, interval], - 0, - '#c2c2c2', - 10, - '#9cfcff', - 30, - '#059bff', - 50, - '#39ff03', - 100, - '#fffb03', - 200, - '#ff9500', - 300, - '#ff0000', - 500, - '#fb00ff', - 1000, - '#960099', - 2000, - '#000000', - ], - circleOpacity: [ - 'case', - [ - '<', + ...({ + interval: CircleLayerProperties( + circleColor: [ + Expressions.interpolate, + ['linear'], [Expressions.get, interval], 0, + '#c2c2c2', + 10, + '#9cfcff', + 30, + '#059bff', + 50, + '#39ff03', + 100, + '#fffb03', + 200, + '#ff9500', + 300, + '#ff0000', + 500, + '#fb00ff', + 1000, + '#960099', + 2000, + '#000000', ], - 0, - 0.7, - ], - circleStrokeWidth: 0.2, - circleStrokeColor: '#000000', - circleStrokeOpacity: [ - 'case', - [ - '<', - [Expressions.get, interval], - 0, + circleRadius: kCircleIconSize, + circleOpacity: 0.75, + circleStrokeColor: colors.outlineVariant.toHexStringRGB(), + circleStrokeWidth: 0.5, + circleStrokeOpacity: 0.75, + visibility: interval == currentPrecipitationInterval.value ? 'visible' : 'none', + ), + '$interval-label': SymbolLayerProperties( + textField: [ + Expressions.concat, + [Expressions.get, 'name'], + '\n', + [ + Expressions.concat, + [Expressions.get, interval], + 'mm', + ], ], - 0, - 0.7, - ], - visibility: interval == currentPrecipitationInterval.value ? 'visible' : 'none', - ), + textSize: 10, + textColor: colors.onSurfaceVariant.toHexStringRGB(), + textHaloColor: colors.outlineVariant.toHexStringRGB(), + textHaloWidth: 1, + textFont: ['Noto Sans TC Bold'], + textOffset: [0, 1], + textAnchor: 'top', + visibility: interval == currentPrecipitationInterval.value ? 'visible' : 'none', + ), + }), }; await Future.wait( - properties.entries.map( - (entry) => controller - .addLayer(sourceId, '$layerId-${entry.key}', entry.value, belowLayerId: BaseMapLayerIds.userLocation) - .then((value) { - TalkerManager.instance.info('Added Layer "$layerId-${entry.key}"'); - }), - ), + properties.entries.map((entry) { + final isValueLayer = entry.key.endsWith('-label'); + final interval = isValueLayer ? entry.key.substring(0, entry.key.length - 6) : entry.key; + + return controller.addLayer( + sourceId, + '$layerId-${entry.key}', + entry.value, + belowLayerId: BaseMapLayerIds.userLocation, + minzoom: isValueLayer ? 10 : null, + filter: [ + Expressions.largerOrEqual, + [Expressions.get, interval], + 0, + ], + ); + }), ); } @@ -240,10 +260,11 @@ class PrecipitationMapLayerManager extends MapLayerManager { final layerId = MapLayerIds.precipitation(currentPrecipitationTime.value); final hideLayerId = '$layerId-${currentPrecipitationInterval.value}'; + final hideValueLayerId = '$layerId-${currentPrecipitationInterval.value}-label'; try { await controller.setLayerVisibility(hideLayerId, false); - TalkerManager.instance.info('Hiding Layer "$hideLayerId"'); + await controller.setLayerVisibility(hideValueLayerId, false); visible = false; } catch (e, s) { @@ -257,14 +278,17 @@ class PrecipitationMapLayerManager extends MapLayerManager { final layerId = MapLayerIds.precipitation(currentPrecipitationTime.value); final showLayerId = '$layerId-${currentPrecipitationInterval.value}'; + final showValueLayerId = '$layerId-${currentPrecipitationInterval.value}-label'; try { await controller.setLayerVisibility(showLayerId, true); - TalkerManager.instance.info('Showing Layer "$showLayerId"'); + await controller.setLayerVisibility(showValueLayerId, true); await _focus(); visible = true; + + if (_lastFetchTime == null || DateTime.now().difference(_lastFetchTime!).inMinutes > 5) await _fetchData(); } catch (e, s) { TalkerManager.instance.error('PrecipitationMapLayerManager.show', e, s); } @@ -278,11 +302,10 @@ class PrecipitationMapLayerManager extends MapLayerManager { for (final interval in precipitationIntervals) { await controller.removeLayer('$layerId-$interval'); - TalkerManager.instance.info('Removed Layer "$layerId-$interval"'); + await controller.removeLayer('$layerId-$interval-label'); } await controller.removeSource(sourceId); - TalkerManager.instance.info('Removed Source "$sourceId"'); } catch (e, s) { TalkerManager.instance.error('PrecipitationMapLayerManager.remove', e, s); } @@ -314,95 +337,51 @@ class PrecipitationMapLayerSheet extends StatelessWidget { _ => interval, }; - return MorphingSheet( - title: '降水'.i18n, - borderRadius: BorderRadius.circular(16), - elevation: 4, - partialBuilder: (context, controller, sheetController) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Selector>( - selector: (context, model) => model.precipitation, - builder: (context, precipitation, header) { - final times = precipitation.map((time) { - final t = time.toSimpleDateTimeString(context).split(' '); - return (date: t[0], time: t[1], value: time); - }); - final grouped = times.groupListsBy((time) => time.date).entries.toList(); - - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - header!, - SizedBox( - height: kMinInteractiveDimension, - child: ValueListenableBuilder( - valueListenable: manager.currentPrecipitationInterval, - builder: (context, currentPrecipitationInterval, child) { - const intervals = PrecipitationMapLayerManager.precipitationIntervals; - - return ListView.separated( - padding: const EdgeInsets.symmetric(horizontal: 16), - scrollDirection: Axis.horizontal, - physics: const AlwaysScrollableScrollPhysics(), - itemCount: intervals.length, - itemBuilder: (context, index) { - final interval = intervals[index]; - final isSelected = interval == currentPrecipitationInterval; - - return ValueListenableBuilder( - valueListenable: manager.isLoading, - builder: (context, isLoading, child) { - return FilterChip( - selected: isSelected, - showCheckmark: !isLoading, - label: Text(getIntervalLabel(interval)), - side: BorderSide( - color: isSelected ? context.colors.primary : context.colors.outlineVariant, - ), - avatar: isSelected && isLoading ? const LoadingIcon() : null, - onSelected: - isLoading - ? null - : (selected) { - if (!selected) return; - manager.setPrecipitationInterval(interval); - }, - ); - }, - ); - }, - separatorBuilder: (context, index) => const SizedBox(width: 8), - ); - }, - ), - ), - SizedBox( - height: kMinInteractiveDimension, - child: ValueListenableBuilder( - valueListenable: manager.currentPrecipitationTime, - builder: (context, currentPrecipitationTime, child) { - return ListView.builder( - padding: const EdgeInsets.symmetric(horizontal: 16), - scrollDirection: Axis.horizontal, - physics: const AlwaysScrollableScrollPhysics(), - itemCount: grouped.length, - itemBuilder: (context, index) { - final MapEntry(key: date, value: group) = grouped[index]; - - final children = [Text(date)]; - - for (final time in group) { - final isSelected = time.value == currentPrecipitationTime; - - children.add( - ValueListenableBuilder( + return Stack( + children: [ + MorphingSheet( + title: '降水'.i18n, + borderRadius: BorderRadius.circular(16), + elevation: 4, + partialBuilder: (context, controller, sheetController) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Selector>( + selector: (context, model) => model.precipitation, + builder: (context, precipitation, header) { + final times = precipitation.map((time) { + final t = time.toSimpleDateTimeString().split(' '); + return (date: t[0], time: t[1], value: time); + }); + final grouped = times.groupListsBy((time) => time.date).entries.toList(); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + header!, + SizedBox( + height: kMinInteractiveDimension, + child: ValueListenableBuilder( + valueListenable: manager.currentPrecipitationInterval, + builder: (context, currentPrecipitationInterval, child) { + const intervals = PrecipitationMapLayerManager.precipitationIntervals; + + return ListView.separated( + padding: const EdgeInsets.symmetric(horizontal: 16), + scrollDirection: Axis.horizontal, + physics: const AlwaysScrollableScrollPhysics(), + itemCount: intervals.length, + itemBuilder: (context, index) { + final interval = intervals[index]; + final isSelected = interval == currentPrecipitationInterval; + + return ValueListenableBuilder( valueListenable: manager.isLoading, builder: (context, isLoading, child) { return FilterChip( selected: isSelected, showCheckmark: !isLoading, - label: Text(time.time), + label: Text(getIntervalLabel(interval)), side: BorderSide( color: isSelected ? context.colors.primary : context.colors.outlineVariant, ), @@ -412,43 +391,116 @@ class PrecipitationMapLayerSheet extends StatelessWidget { ? null : (selected) { if (!selected) return; - manager.setPrecipitationTime(time.value); + manager.setPrecipitationInterval(interval); }, ); }, - ), - ); - } - - children.add( - const Padding( - padding: EdgeInsets.only(right: 8), - child: VerticalDivider(width: 16, indent: 8, endIndent: 8), - ), + ); + }, + separatorBuilder: (context, index) => const SizedBox(width: 8), ); + }, + ), + ), + SizedBox( + height: kMinInteractiveDimension, + child: ValueListenableBuilder( + valueListenable: manager.currentPrecipitationTime, + builder: (context, currentPrecipitationTime, child) { + return ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 16), + scrollDirection: Axis.horizontal, + physics: const AlwaysScrollableScrollPhysics(), + itemCount: grouped.length, + itemBuilder: (context, index) { + final MapEntry(key: date, value: group) = grouped[index]; + + final children = [Text(date)]; + + for (final time in group) { + final isSelected = time.value == currentPrecipitationTime; + + children.add( + ValueListenableBuilder( + valueListenable: manager.isLoading, + builder: (context, isLoading, child) { + return FilterChip( + selected: isSelected, + showCheckmark: !isLoading, + label: Text(time.time), + side: BorderSide( + color: isSelected ? context.colors.primary : context.colors.outlineVariant, + ), + avatar: isSelected && isLoading ? const LoadingIcon() : null, + onSelected: + isLoading + ? null + : (selected) { + if (!selected) return; + manager.setPrecipitationTime(time.value); + }, + ); + }, + ), + ); + } + + children.add( + const Padding( + padding: EdgeInsets.only(right: 8), + child: VerticalDivider(width: 16, indent: 8, endIndent: 8), + ), + ); - return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: children); + return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: children); + }, + ); }, - ); - }, - ), + ), + ), + ], + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + spacing: 8, + children: [ + const Icon(Symbols.water_drop_rounded, size: 24), + Text('降水'.i18n, style: context.textTheme.titleMedium), + ], ), - ], - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - spacing: 8, - children: [ - const Icon(Symbols.water_drop_rounded, size: 24), - Text('降水'.i18n, style: context.textTheme.titleMedium), + ), + ), + ); + }, + ), + Positioned( + top: 24 + 48 + 16, + left: 24, + child: SafeArea( + child: BlurredContainer( + elevation: 4, + shadowColor: context.colors.shadow.withValues(alpha: 0.4), + child: ColorLegend( + unit: 'mm', + items: [ + ColorLegendItem(color: const Color(0xffc2c2c2), value: 0), + ColorLegendItem(color: const Color(0xFF9CFCFF), value: 10), + ColorLegendItem(color: const Color(0xFF059BFF), value: 30), + ColorLegendItem(color: const Color(0xFF39FF03), value: 50), + ColorLegendItem(color: const Color(0xFFFFFB03), value: 100), + ColorLegendItem(color: const Color(0xFFFF9500), value: 200), + ColorLegendItem(color: const Color(0xFFFF0000), value: 300), + ColorLegendItem(color: const Color(0xFFFB00FF), value: 500), + ColorLegendItem(color: const Color(0xFF960099), value: 1000), + ColorLegendItem(color: const Color(0xFF000000), value: 2000), ], ), ), ), - ); - }, + ), + ], ); } } diff --git a/lib/app/map/_lib/managers/radar.dart b/lib/app/map/_lib/managers/radar.dart index a25a4e56a..1f5a3e245 100644 --- a/lib/app/map/_lib/managers/radar.dart +++ b/lib/app/map/_lib/managers/radar.dart @@ -1,9 +1,17 @@ import 'dart:async'; +import 'package:flutter/material.dart'; + import 'package:collection/collection.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/api/exptech.dart'; +import 'package:dpip/api/route.dart'; import 'package:dpip/app/map/_lib/manager.dart'; import 'package:dpip/app/map/_lib/utils.dart'; +import 'package:dpip/app/map/_widgets/map_legend.dart'; import 'package:dpip/core/i18n.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/models/data.dart'; @@ -11,13 +19,10 @@ import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/extensions/string.dart'; import 'package:dpip/utils/log.dart'; +import 'package:dpip/widgets/blurred_container.dart'; import 'package:dpip/widgets/map/map.dart'; import 'package:dpip/widgets/sheet/morphing_sheet.dart'; import 'package:dpip/widgets/ui/loading_icon.dart'; -import 'package:flutter/material.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; class RadarMapLayerManager extends MapLayerManager { RadarMapLayerManager(super.context, super.controller, {this.getActiveLayerCount}); @@ -28,6 +33,8 @@ class RadarMapLayerManager extends MapLayerManager { final playStartTime = ValueNotifier(null); final playEndTime = ValueNotifier(null); + DateTime? _lastFetchTime; + Timer? _playTimer; final Set _preloadedLayers = {}; final int Function()? getActiveLayerCount; @@ -133,8 +140,6 @@ class RadarMapLayerManager extends MapLayerManager { currentRadarTime.value = time; await _setupAndShowLayer(time); - - TalkerManager.instance.info('Updated Radar tiles to "$time"'); } catch (e, s) { TalkerManager.instance.error('RadarMapLayerManager._updateRadarTileUrl', e, s); } finally { @@ -150,20 +155,15 @@ class RadarMapLayerManager extends MapLayerManager { final isLayerExists = (await controller.getLayerIds()).contains(layerId); if (!isSourceExists) { - final properties = RasterSourceProperties( - tiles: ['https://api-1.exptech.dev/api/v1/tiles/radar/$time/{z}/{x}/{y}.png'], - tileSize: 256, - ); + final properties = RasterSourceProperties(tiles: [Routes.radarTile(time)], tileSize: 256); await controller.addSource(sourceId, properties); - TalkerManager.instance.info('Added Source "$sourceId"'); } if (!isLayerExists) { final properties = RasterLayerProperties(visibility: visible ? 'visible' : 'none'); await controller.addLayer(sourceId, layerId, properties, belowLayerId: BaseMapLayerIds.exptechCountyOutline); - TalkerManager.instance.info('Added Layer "$layerId"'); } else if (visible) { await controller.setLayerVisibility(layerId, true); } @@ -204,7 +204,6 @@ class RadarMapLayerManager extends MapLayerManager { try { await _setupAndShowLayer(time); await _hideLayer(time); - TalkerManager.instance.info('Preloaded radar layer: $time'); } catch (e, s) { TalkerManager.instance.error('Failed to preload radar layer: $time', e, s); } @@ -314,11 +313,10 @@ class RadarMapLayerManager extends MapLayerManager { Future _focus() async { try { - final location = GlobalProviders.location.coordinateNotifier.value; + final location = GlobalProviders.location.coordinates; - if (location.isValid) { + if (location != null && location.isValid) { await controller.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); - TalkerManager.instance.info('Moved Camera to $location'); } else { await controller.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); TalkerManager.instance.info('Moved Camera to ${DpipMap.kTaiwanCenter}'); @@ -328,21 +326,27 @@ class RadarMapLayerManager extends MapLayerManager { } } + Future _fetchData() async { + final radarList = (await ExpTech().getRadarList()).reversed.toList(); + if (!context.mounted) return; + + GlobalProviders.data.setRadar(radarList); + currentRadarTime.value ??= radarList.first; + _lastFetchTime = DateTime.now(); + } + @override Future setup() async { if (didSetup) return; try { - if (GlobalProviders.data.radar.isEmpty) { - final radarList = (await ExpTech().getRadarList()).reversed.toList(); - if (!context.mounted) return; + if (GlobalProviders.data.radar.isEmpty) await _fetchData(); - GlobalProviders.data.setRadar(radarList); - currentRadarTime.value = radarList.first; - } + final time = currentRadarTime.value; + if (time == null) throw Exception('Time is null'); - await _setupAndShowLayer(currentRadarTime.value!); - await _preloadAdjacentLayers(currentRadarTime.value!); + await _setupAndShowLayer(time); + await _preloadAdjacentLayers(time); didSetup = true; } catch (e, s) { @@ -362,7 +366,6 @@ class RadarMapLayerManager extends MapLayerManager { } visible = false; - TalkerManager.instance.info('Hidden all radar layers'); } catch (e, s) { TalkerManager.instance.error('RadarMapLayerManager.hide', e, s); } @@ -376,12 +379,13 @@ class RadarMapLayerManager extends MapLayerManager { if (currentRadarTime.value != null) { final layerId = MapLayerIds.radar(currentRadarTime.value); await controller.setLayerVisibility(layerId, true); - TalkerManager.instance.info('Showing Layer "$layerId"'); } await _focus(); visible = true; + + if (_lastFetchTime == null || DateTime.now().difference(_lastFetchTime!).inMinutes > 5) await _fetchData(); } catch (e, s) { TalkerManager.instance.error('RadarMapLayerManager.show', e, s); } @@ -464,230 +468,265 @@ class RadarMapLayerSheet extends StatelessWidget { @override Widget build(BuildContext context) { - return MorphingSheet( - title: '雷達回波'.i18n, - borderRadius: BorderRadius.circular(16), - elevation: 4, - partialBuilder: (context, controller, sheetController) { - return Padding( - padding: const EdgeInsets.only(top: 4, bottom: 8), - child: Selector>( - selector: (context, model) => model.radar, - builder: (context, radar, child) { - final times = radar.map((time) { - final t = time.toSimpleDateTimeString(context).split(' '); - return (date: t[0], time: t[1], value: time); - }); - final grouped = times.groupListsBy((time) => time.date).entries.toList(); - - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 16, right: 4), - child: SizedBox( - height: 48, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - spacing: 8, + return Stack( + children: [ + MorphingSheet( + title: '雷達回波'.i18n, + borderRadius: BorderRadius.circular(16), + elevation: 4, + partialBuilder: (context, controller, sheetController) { + return Padding( + padding: const EdgeInsets.only(top: 4, bottom: 8), + child: Selector>( + selector: (context, model) => model.radar, + builder: (context, radar, child) { + final times = radar.map((time) { + final t = time.toSimpleDateTimeString().split(' '); + return (date: t[0], time: t[1], value: time); + }); + final grouped = times.groupListsBy((time) => time.date).entries.toList(); + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 16, right: 4), + child: SizedBox( + height: 48, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon(Symbols.radar_rounded, size: 24, color: context.colors.onSurface), - Text( - '雷達回波'.i18n, - style: context.textTheme.titleMedium?.copyWith(color: context.colors.onSurface), + Row( + spacing: 8, + children: [ + Icon(Symbols.radar_rounded, size: 24, color: context.colors.onSurface), + Text( + '雷達回波'.i18n, + style: context.textTheme.titleMedium?.copyWith(color: context.colors.onSurface), + ), + AnimatedBuilder( + animation: Listenable.merge([ + manager.currentRadarTime, + manager.playStartTime, + manager.isPlaying, + ]), + builder: (context, child) { + final currentTime = manager.currentRadarTime.value; + + if (currentTime == null) return const SizedBox.shrink(); + + try { + final timeFormatted = currentTime.toSimpleDateTimeString(); + final timeData = timeFormatted.split(' '); + final date = timeData.length > 1 ? timeData[0] : ''; + final time = timeData.length > 1 ? timeData[1] : timeData[0]; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5), + decoration: BoxDecoration( + color: context.colors.surfaceContainer.withValues(alpha: 0.6), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: context.colors.outline), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + Icon( + Icons.schedule_rounded, + size: 12, + color: context.colors.onSurfaceVariant, + ), + if (date.isNotEmpty) ...[ + Text( + date, + style: context.textTheme.labelSmall?.copyWith( + color: context.colors.onSurfaceVariant, + height: 1, + ), + ), + Container( + width: 0.5, + height: 14, + margin: const EdgeInsets.symmetric(horizontal: 2), + color: context.colors.outline, + ), + ], + Text( + time, + style: context.textTheme.bodySmall?.copyWith( + color: context.colors.onSurface, + fontWeight: FontWeight.bold, + height: 1, + ), + ), + ], + ), + ); + } catch (e) { + return const SizedBox.shrink(); + } + }, + ), + ], ), AnimatedBuilder( animation: Listenable.merge([ - manager.currentRadarTime, - manager.playStartTime, manager.isPlaying, + manager.playStartTime, + manager.currentRadarTime, ]), builder: (context, child) { - final currentTime = manager.currentRadarTime.value; - - if (currentTime == null) return const SizedBox.shrink(); - - try { - final timeFormatted = currentTime.toSimpleDateTimeString(context); - final timeData = timeFormatted.split(' '); - final date = timeData.length > 1 ? timeData[0] : ''; - final time = timeData.length > 1 ? timeData[1] : timeData[0]; - - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5), - decoration: BoxDecoration( - color: context.colors.surfaceContainer.withValues(alpha: 0.6), - borderRadius: BorderRadius.circular(8), - border: Border.all(color: context.colors.outline), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - spacing: 4, - children: [ - Icon( - Icons.schedule_rounded, - size: 12, - color: context.colors.onSurfaceVariant, - ), - if (date.isNotEmpty) ...[ - Text( - date, - style: context.textTheme.labelSmall?.copyWith( - color: context.colors.onSurfaceVariant, - height: 1, - ), - ), - Container( - width: 0.5, - height: 14, - margin: const EdgeInsets.symmetric(horizontal: 2), - color: context.colors.outline, - ), - ], - Text( - time, - style: context.textTheme.bodySmall?.copyWith( - color: context.colors.onSurface, - fontWeight: FontWeight.bold, - height: 1, - ), - ), - ], - ), - ); - } catch (e) { + final isPlaying = manager.isPlaying.value; + final startTime = manager.playStartTime.value; + final canPlay = manager.canPlay; + + final shouldHide = startTime == null && !isPlaying; + + if (shouldHide) { return const SizedBox.shrink(); } + + return IconButton( + onPressed: canPlay || isPlaying ? manager.toggleAutoPlay : null, + icon: Icon( + isPlaying ? Symbols.pause_rounded : Symbols.play_arrow_rounded, + size: 24, + color: context.colors.primary, + ), + ); }, ), ], ), - AnimatedBuilder( - animation: Listenable.merge([ - manager.isPlaying, - manager.playStartTime, - manager.currentRadarTime, - ]), - builder: (context, child) { - final isPlaying = manager.isPlaying.value; - final startTime = manager.playStartTime.value; - final canPlay = manager.canPlay; - - final shouldHide = startTime == null && !isPlaying; - - if (shouldHide) { - return const SizedBox.shrink(); - } - - return IconButton( - onPressed: canPlay || isPlaying ? manager.toggleAutoPlay : null, - icon: Icon( - isPlaying ? Symbols.pause_rounded : Symbols.play_arrow_rounded, - size: 24, - color: context.colors.primary, - ), - ); - }, - ), - ], + ), ), - ), - ), - AnimatedBuilder( - animation: Listenable.merge([manager.playStartTime, manager.isPlaying]), - builder: (context, child) { - final startTime = manager.playStartTime.value; - final isPlaying = manager.isPlaying.value; - - if (isPlaying) { - return const SizedBox.shrink(); - } - - if (startTime == null && !isPlaying) { - return Padding( - padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), - child: Text( - '長按設定播放起點'.i18n, - style: context.textTheme.bodySmall?.copyWith(color: context.colors.onSurfaceVariant), - ), - ); - } - - return Padding( - padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), - child: Column( - children: [ - Row( - spacing: 8, + AnimatedBuilder( + animation: Listenable.merge([manager.playStartTime, manager.isPlaying]), + builder: (context, child) { + final startTime = manager.playStartTime.value; + final isPlaying = manager.isPlaying.value; + + if (isPlaying) { + return const SizedBox.shrink(); + } + + if (startTime == null && !isPlaying) { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), + child: Text( + '長按設定播放起點'.i18n, + style: context.textTheme.bodySmall?.copyWith(color: context.colors.onSurfaceVariant), + ), + ); + } + + return Padding( + padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), + child: Column( children: [ - _LegendItem( - label: '目前時間'.i18n, - color: context.colors.primaryContainer, - borderColor: context.colors.primary, - ), - _LegendItem( - label: '播放起點'.i18n, - color: context.colors.tertiaryContainer, - borderColor: context.colors.tertiary, + Row( + spacing: 8, + children: [ + _LegendItem( + label: '目前時間'.i18n, + color: context.colors.primaryContainer, + borderColor: context.colors.primary, + ), + _LegendItem( + label: '播放起點'.i18n, + color: context.colors.tertiaryContainer, + borderColor: context.colors.tertiary, + ), + ], ), ], ), - ], - ), - ); - }, - ), - ValueListenableBuilder( - valueListenable: manager.isPlaying, - builder: (context, isPlaying, child) { - if (isPlaying) { - return Container( - height: 32, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - child: AnimatedBuilder( - animation: Listenable.merge([ - manager.currentRadarTime, - manager.playStartTime, - manager.playEndTime, - ]), - builder: (context, child) { - return _RadarProgressBar(manager: manager); - }, - ), - ); - } - - return SizedBox( - height: kMinInteractiveDimension, - child: ValueListenableBuilder( - valueListenable: manager.currentRadarTime, - builder: (context, currentTime, child) { - return ValueListenableBuilder( - valueListenable: manager.playStartTime, - builder: (context, startTime, child) { - return _AutoScrollingTimeList( - grouped: grouped, - currentTime: currentTime, - startTime: startTime, - manager: manager, - shouldFocusOnShow: true, + ); + }, + ), + ValueListenableBuilder( + valueListenable: manager.isPlaying, + builder: (context, isPlaying, child) { + if (isPlaying) { + return Container( + height: 32, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: AnimatedBuilder( + animation: Listenable.merge([ + manager.currentRadarTime, + manager.playStartTime, + manager.playEndTime, + ]), + builder: (context, child) { + return _RadarProgressBar(manager: manager); + }, + ), + ); + } + + return SizedBox( + height: kMinInteractiveDimension, + child: ValueListenableBuilder( + valueListenable: manager.currentRadarTime, + builder: (context, currentTime, child) { + return ValueListenableBuilder( + valueListenable: manager.playStartTime, + builder: (context, startTime, child) { + return _AutoScrollingTimeList( + grouped: grouped, + currentTime: currentTime, + startTime: startTime, + manager: manager, + shouldFocusOnShow: true, + ); + }, ); }, - ); - }, - ), - ); - }, - ), + ), + ); + }, + ), + ], + ); + }, + ), + ); + }, + ), + Positioned( + top: 24 + 48 + 16, + left: 24, + child: SafeArea( + child: BlurredContainer( + elevation: 4, + shadowColor: context.colors.shadow.withValues(alpha: 0.4), + child: ColorLegend( + reverse: true, + unit: 'dBZ', + items: [ + ColorLegendItem(color: const Color(0xff00ffff), value: 0), + ColorLegendItem(color: const Color(0xff00a3ff), value: 5), + ColorLegendItem(color: const Color(0xff005bff), value: 10), + ColorLegendItem(color: const Color(0xff0000ff), value: 15, blendTail: false), + ColorLegendItem(color: const Color(0xff00ff00), value: 16, hidden: true), + ColorLegendItem(color: const Color(0xff00d300), value: 20), + ColorLegendItem(color: const Color(0xff00a000), value: 25), + ColorLegendItem(color: const Color(0xffccea00), value: 30), + ColorLegendItem(color: const Color(0xffffd300), value: 35), + ColorLegendItem(color: const Color(0xffff8800), value: 40), + ColorLegendItem(color: const Color(0xffff1800), value: 45), + ColorLegendItem(color: const Color(0xffd30000), value: 50), + ColorLegendItem(color: const Color(0xffa00000), value: 55), + ColorLegendItem(color: const Color(0xffea00cc), value: 60), + ColorLegendItem(color: const Color(0xff9600ff), value: 65), ], - ); - }, + ), + ), ), - ); - }, + ), + ], ); } } @@ -754,35 +793,28 @@ class _AutoScrollingTimeListState extends State<_AutoScrollingTimeList> { final key = _chipKeys[widget.currentTime]; if (key?.currentContext == null) return; - try { - final RenderBox? renderBox = key!.currentContext!.findRenderObject() as RenderBox?; - if (renderBox == null) return; + final RenderBox? renderBox = key!.currentContext!.findRenderObject() as RenderBox?; + if (renderBox == null) return; - final RenderBox? scrollViewBox = - _scrollController.position.context.storageContext.findRenderObject() as RenderBox?; - if (scrollViewBox == null) return; + final RenderBox? scrollViewBox = _scrollController.position.context.storageContext.findRenderObject() as RenderBox?; + if (scrollViewBox == null) return; - if (!renderBox.attached) return; + if (!renderBox.attached) return; - final position = renderBox.localToGlobal(Offset.zero); - final localPosition = scrollViewBox.globalToLocal(position); + final position = renderBox.localToGlobal(Offset.zero); + final localPosition = scrollViewBox.globalToLocal(position); - final targetOffset = - _scrollController.offset + localPosition.dx - (scrollViewBox.size.width / 2) + (renderBox.size.width / 2); + final targetOffset = + _scrollController.offset + localPosition.dx - (scrollViewBox.size.width / 2) + (renderBox.size.width / 2); - final clampedOffset = targetOffset.clamp( - _scrollController.position.minScrollExtent, - _scrollController.position.maxScrollExtent, - ); + final clampedOffset = targetOffset.clamp( + _scrollController.position.minScrollExtent, + _scrollController.position.maxScrollExtent, + ); - if ((clampedOffset - _scrollController.offset).abs() > 20) { - _scrollController.animateTo( - clampedOffset, - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, - ); - } - } catch (e) {} + if ((clampedOffset - _scrollController.offset).abs() > 20) { + _scrollController.animateTo(clampedOffset, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut); + } } @override diff --git a/lib/app/map/_lib/managers/report.dart b/lib/app/map/_lib/managers/report.dart index 519387941..fb71fa5ce 100644 --- a/lib/app/map/_lib/managers/report.dart +++ b/lib/app/map/_lib/managers/report.dart @@ -9,6 +9,7 @@ import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:dpip/api/exptech.dart'; +import 'package:dpip/api/model/location/location.dart'; import 'package:dpip/api/model/report/earthquake_report.dart'; import 'package:dpip/api/model/report/partial_earthquake_report.dart'; import 'package:dpip/app/map/_lib/manager.dart'; @@ -44,6 +45,8 @@ class ReportMapLayerManager extends MapLayerManager { final currentReport = ValueNotifier(null); final isLoading = ValueNotifier(false); + DateTime? _lastFetchTime; + Future setReport(String? reportId, {bool focus = true}) async { if (isLoading.value) return; @@ -95,17 +98,20 @@ class ReportMapLayerManager extends MapLayerManager { ); } + Future _fetchData() async { + final reportList = await ExpTech().getReportList(); + if (!context.mounted) return; + + GlobalProviders.data.setPartialReport(reportList); + _lastFetchTime = DateTime.now(); + } + @override Future setup() async { if (didSetup) return; try { - if (GlobalProviders.data.partialReport.isEmpty) { - final reportList = await ExpTech().getReportList(); - if (!context.mounted) return; - - GlobalProviders.data.setPartialReport(reportList); - } + if (GlobalProviders.data.partialReport.isEmpty) await _fetchData(); final sourceId = MapSourceIds.report(); final layerId = MapLayerIds.report(); @@ -124,7 +130,6 @@ class ReportMapLayerManager extends MapLayerManager { final properties = GeojsonSourceProperties(data: data); await controller.addSource(sourceId, properties); - TalkerManager.instance.info('Added Source "$sourceId"'); if (!context.mounted) return; } @@ -157,8 +162,6 @@ class ReportMapLayerManager extends MapLayerManager { ); await controller.addLayer(sourceId, layerId, properties, belowLayerId: BaseMapLayerIds.userLocation); - - TalkerManager.instance.info('Added Layer "$layerId"'); } didSetup = true; @@ -179,7 +182,6 @@ class ReportMapLayerManager extends MapLayerManager { try { await controller.setLayerVisibility(layerId, false); - TalkerManager.instance.info('Hiding Layer "$layerId"'); visible = false; } catch (e, s) { @@ -199,12 +201,13 @@ class ReportMapLayerManager extends MapLayerManager { initialReportId = null; } else { await controller.setLayerVisibility(layerId, true); - TalkerManager.instance.info('Showing Layer "$layerId"'); await _focus(); } visible = true; + + if (_lastFetchTime == null || DateTime.now().difference(_lastFetchTime!).inMinutes > 5) await _fetchData(); } catch (e, s) { TalkerManager.instance.error('ReportMapLayerManager.show', e, s); } @@ -217,10 +220,7 @@ class ReportMapLayerManager extends MapLayerManager { final sourceId = MapSourceIds.report(); await controller.removeLayer(layerId); - TalkerManager.instance.info('Removed Layer "$layerId"'); - await controller.removeSource(sourceId); - TalkerManager.instance.info('Removed Source "$sourceId"'); } catch (e, s) { TalkerManager.instance.error('ReportMapLayerManager.dispose', e, s); } @@ -261,7 +261,6 @@ class ReportMapLayerManager extends MapLayerManager { final properties = GeojsonSourceProperties(data: data); await controller.addSource(sourceId, properties); - TalkerManager.instance.info('Added Source "$sourceId"'); if (!context.mounted) return; } @@ -276,13 +275,11 @@ class ReportMapLayerManager extends MapLayerManager { ); await controller.addLayer(sourceId, layerId, properties, belowLayerId: BaseMapLayerIds.userLocation); - TalkerManager.instance.info('Added Layer "$layerId"'); } if (focus) await _focus(report); await controller.setLayerVisibility(MapLayerIds.report(), false); - TalkerManager.instance.info('Hiding Layer "$layerId"'); } catch (e, s) { TalkerManager.instance.error('ReportMapLayerManager._addReport', e, s); } @@ -300,18 +297,15 @@ class ReportMapLayerManager extends MapLayerManager { if (isLayerExists) { await controller.removeLayer(layerId); - TalkerManager.instance.info('Removed Layer "$layerId"'); } if (isSourceExists) { await controller.removeSource(sourceId); - TalkerManager.instance.info('Removed Source "$sourceId"'); } if (focus) await _focus(); await controller.setLayerVisibility(MapLayerIds.report(), true); - TalkerManager.instance.info('Showing Layer "$layerId"'); } catch (e, s) { TalkerManager.instance.error('ReportMapLayerManager._removeReport', e, s); } @@ -348,9 +342,13 @@ class _ReportMapLayerSheetState extends State { return ValueListenableBuilder( valueListenable: widget.manager.currentReport, builder: (context, currentReport, child) { + // Show the first report from partial report list if (currentReport == null) { final report = GlobalProviders.data.partialReport.first; + final locationString = report.extractLocation(); + final location = Location.tryParse(locationString)?.dynamicName ?? locationString; + return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Selector>( @@ -399,7 +397,7 @@ class _ReportMapLayerSheetState extends State { Text( report.hasNumber ? '編號 {number} 顯著有感地震'.i18n.args({'number': report.number}) - : report.extractLocation(), + : location, style: context.textTheme.titleMedium, ), Text( @@ -422,6 +420,11 @@ class _ReportMapLayerSheetState extends State { ); } + // Show the current report with details + + final locationString = currentReport.extractLocation(); + final location = Location.tryParse(locationString)?.dynamicName ?? locationString; + return Padding( padding: const EdgeInsets.all(12), child: Column( @@ -444,10 +447,7 @@ class _ReportMapLayerSheetState extends State { : '小區域有感地震'.i18n, style: context.textTheme.labelMedium?.copyWith(color: context.colors.outline), ), - Text( - currentReport.extractLocation(), - style: context.textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w500), - ), + Text(location, style: context.textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w500)), Text( currentReport.time.toLocaleDateTimeString(context), style: context.textTheme.bodyMedium?.copyWith(color: context.colors.onSurfaceVariant), @@ -536,31 +536,35 @@ class _ReportMapLayerSheetState extends State { itemCount: grouped.length, itemBuilder: (context, index) { final MapEntry(key: date, value: reports) = grouped[index]; + return ListSection( title: date, - children: [ - for (final report in reports) - ListSectionTile( - leading: IntensityBox( - intensity: report.intensity, - size: 36, - borderRadius: 8, - border: !report.hasNumber, - ), - title: report.extractLocation(), - subtitle: Text( - '${report.hasNumber ? '${'編號 {number} 顯著有感地震'.i18n.args({'number': report.number})}\n' : ''}${report.time.toLocaleTimeString(context)}・${report.depth}km', - ), - trailing: Text( - 'M ${report.magnitude.toStringAsFixed(1)}', - style: context.textTheme.labelLarge, - ), - onTap: () { - widget.manager.setReport(report.id); - sheetController.collapse(); - }, - ), - ], + children: + reports.map((report) { + final locationString = report.extractLocation(); + final location = Location.tryParse(locationString)?.dynamicName ?? locationString; + + return ListSectionTile( + leading: IntensityBox( + intensity: report.intensity, + size: 36, + borderRadius: 8, + border: !report.hasNumber, + ), + title: location, + subtitle: Text( + '${report.hasNumber ? '${'編號 {number} 顯著有感地震'.i18n.args({'number': report.number})}\n' : ''}${report.time.toLocaleTimeString(context)}・${report.depth}km', + ), + trailing: Text( + 'M ${report.magnitude.toStringAsFixed(1)}', + style: context.textTheme.labelLarge, + ), + onTap: () { + widget.manager.setReport(report.id); + sheetController.collapse(); + }, + ); + }).toList(), ); }, ), @@ -576,6 +580,9 @@ class _ReportMapLayerSheetState extends State { if (report == null) { content = [const Center(child: CircularProgressIndicator())]; } else { + final locationString = report.getLocation(); + final location = Location.tryParse(locationString)?.dynamicName ?? locationString; + content = [ Padding( padding: const EdgeInsets.symmetric(vertical: 8), @@ -593,10 +600,7 @@ class _ReportMapLayerSheetState extends State { : '小區域有感地震'.i18n, style: TextStyle(color: context.colors.onSurfaceVariant, fontSize: 14), ), - Text( - report.getLocation(), - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), + Text(location, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), ], ), ), @@ -680,7 +684,7 @@ class _ReportMapLayerSheetState extends State { margin: const EdgeInsets.only(right: 6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - color: DepthColor.depth(report.depth), + color: getDepthColor(report.depth), ), ), Text( diff --git a/lib/app/map/_lib/managers/temperature.dart b/lib/app/map/_lib/managers/temperature.dart index 6a967fdfc..5dbfd2428 100644 --- a/lib/app/map/_lib/managers/temperature.dart +++ b/lib/app/map/_lib/managers/temperature.dart @@ -1,23 +1,30 @@ +import 'package:flutter/material.dart'; + import 'package:collection/collection.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/api/exptech.dart'; import 'package:dpip/api/model/weather/weather.dart'; import 'package:dpip/app/map/_lib/manager.dart'; import 'package:dpip/app/map/_lib/utils.dart'; +import 'package:dpip/app/map/_widgets/map_legend.dart'; import 'package:dpip/core/i18n.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/models/data.dart'; +import 'package:dpip/models/settings/ui.dart'; +import 'package:dpip/utils/constants.dart'; import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/utils/extensions/int.dart'; import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/extensions/string.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/log.dart'; +import 'package:dpip/widgets/blurred_container.dart'; import 'package:dpip/widgets/map/map.dart'; import 'package:dpip/widgets/sheet/morphing_sheet.dart'; import 'package:dpip/widgets/ui/loading_icon.dart'; -import 'package:flutter/material.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; class TemperatureData { final double latitude; @@ -45,6 +52,8 @@ class TemperatureMapLayerManager extends MapLayerManager { final currentTemperatureTime = ValueNotifier(GlobalProviders.data.temperature.firstOrNull); final isLoading = ValueNotifier(false); + DateTime? _lastFetchTime; + Function(String)? onTimeChanged; Future setTemperatureTime(String time) async { @@ -58,8 +67,6 @@ class TemperatureMapLayerManager extends MapLayerManager { await setup(); onTimeChanged?.call(time); - - TalkerManager.instance.info('Updated Temperature data time to "$time"'); } catch (e, s) { TalkerManager.instance.error('TemperatureMapLayerManager.setTemperatureTime', e, s); } finally { @@ -69,32 +76,39 @@ class TemperatureMapLayerManager extends MapLayerManager { Future _focus() async { try { - final location = GlobalProviders.location.coordinateNotifier.value; + final location = GlobalProviders.location.coordinates; - if (location.isValid) { + if (location != null && location.isValid) { await controller.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); - TalkerManager.instance.info('Moved Camera to $location'); } else { await controller.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); - TalkerManager.instance.info('Moved Camera to ${DpipMap.kTaiwanCenter}'); } } catch (e, s) { TalkerManager.instance.error('TemperatureMapLayerManager._focus', e, s); } } + Future _fetchData() async { + try { + final temperatureList = (await ExpTech().getWeatherList()).reversed.toList(); + if (!context.mounted) return; + + GlobalProviders.data.setTemperature(temperatureList); + currentTemperatureTime.value ??= temperatureList.first; + _lastFetchTime = DateTime.now(); + } catch (e, s) { + TalkerManager.instance.error('TemperatureMapLayerManager._fetchData', e, s); + } + } + @override Future setup() async { if (didSetup) return; - try { - if (GlobalProviders.data.temperature.isEmpty) { - final temperatureList = (await ExpTech().getWeatherList()).reversed.toList(); - if (!context.mounted) return; + final colors = context.colors; - GlobalProviders.data.setTemperature(temperatureList); - currentTemperatureTime.value = temperatureList.first; - } + try { + if (GlobalProviders.data.temperature.isEmpty) await _fetchData(); final time = currentTemperatureTime.value; @@ -127,22 +141,13 @@ class TemperatureMapLayerManager extends MapLayerManager { final properties = GeojsonSourceProperties(data: data); await controller.addSource(sourceId, properties); - TalkerManager.instance.info('Added Source "$sourceId"'); if (!context.mounted) return; } if (!isLayerExists) { + // circles final properties = CircleLayerProperties( - circleRadius: [ - Expressions.interpolate, - ['linear'], - [Expressions.zoom], - 7, - 5, - 12, - 15, - ], circleColor: [ Expressions.interpolate, ['linear'], @@ -162,15 +167,57 @@ class TemperatureMapLayerManager extends MapLayerManager { 40, '#8B0000', ], - circleOpacity: 0.7, - circleStrokeWidth: 0.2, - circleStrokeColor: '#000000', - circleStrokeOpacity: 0.7, + circleRadius: kCircleIconSize, + circleOpacity: 0.75, + circleStrokeColor: colors.outlineVariant.toHexStringRGB(), + circleStrokeWidth: 0.5, + circleStrokeOpacity: 0.75, + visibility: visible ? 'visible' : 'none', + ); + + // labels + final temperature = [ + Expressions.caseExpression, + GlobalProviders.ui.useFahrenheit, + [ + Expressions.round, + [ + Expressions.plus, + [ + Expressions.multiply, + [Expressions.get, 'temperature'], + 1.8, + ], + 32, + ], + ], + [Expressions.get, 'temperature'], + ]; + final properties2 = SymbolLayerProperties( + textField: [ + Expressions.concat, + [Expressions.get, 'name'], + '\n', + [Expressions.concat, temperature, if (GlobalProviders.ui.useFahrenheit) '℉' else '℃'], + ], + textSize: 10, + textColor: colors.onSurfaceVariant.toHexStringRGB(), + textHaloColor: colors.outlineVariant.toHexStringRGB(), + textHaloWidth: 1, + textFont: ['Noto Sans TC Bold'], + textOffset: [0, 1], + textAnchor: 'top', visibility: visible ? 'visible' : 'none', ); await controller.addLayer(sourceId, layerId, properties, belowLayerId: BaseMapLayerIds.userLocation); - TalkerManager.instance.info('Added Layer "$layerId"'); + await controller.addLayer( + sourceId, + '$layerId-label', + properties2, + belowLayerId: BaseMapLayerIds.userLocation, + minzoom: 10, + ); } if (isSourceExists && isLayerExists) return; @@ -189,7 +236,7 @@ class TemperatureMapLayerManager extends MapLayerManager { try { await controller.setLayerVisibility(layerId, false); - TalkerManager.instance.info('Hiding Layer "$layerId"'); + await controller.setLayerVisibility('$layerId-label', false); visible = false; } catch (e, s) { @@ -205,11 +252,13 @@ class TemperatureMapLayerManager extends MapLayerManager { try { await controller.setLayerVisibility(layerId, true); - TalkerManager.instance.info('Showing Layer "$layerId"'); + await controller.setLayerVisibility('$layerId-label', true); await _focus(); visible = true; + + if (_lastFetchTime == null || DateTime.now().difference(_lastFetchTime!).inMinutes > 5) await _fetchData(); } catch (e, s) { TalkerManager.instance.error('TemperatureMapLayerManager.show', e, s); } @@ -222,10 +271,9 @@ class TemperatureMapLayerManager extends MapLayerManager { final sourceId = MapSourceIds.temperature(currentTemperatureTime.value); await controller.removeLayer(layerId); - TalkerManager.instance.info('Removed Layer "$layerId"'); + await controller.removeLayer('$layerId-label'); await controller.removeSource(sourceId); - TalkerManager.instance.info('Removed Source "$sourceId"'); } catch (e, s) { TalkerManager.instance.error('TemperatureMapLayerManager.remove', e, s); } @@ -244,98 +292,131 @@ class TemperatureMapLayerSheet extends StatelessWidget { @override Widget build(BuildContext context) { - return MorphingSheet( - title: '氣溫'.i18n, - borderRadius: BorderRadius.circular(16), - elevation: 4, - partialBuilder: (context, controller, sheetController) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Selector>( - selector: (context, model) => model.temperature, - builder: (context, temperature, header) { - final times = temperature.map((time) { - final t = time.toSimpleDateTimeString(context).split(' '); - return (date: t[0], time: t[1], value: time); - }); - final grouped = times.groupListsBy((time) => time.date).entries.toList(); - - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - header!, - SizedBox( - height: kMinInteractiveDimension, - child: ValueListenableBuilder( - valueListenable: manager.currentTemperatureTime, - builder: (context, currentTemperatureTime, child) { - return ListView.builder( - padding: const EdgeInsets.symmetric(horizontal: 16), - scrollDirection: Axis.horizontal, - physics: const AlwaysScrollableScrollPhysics(), - itemCount: grouped.length, - itemBuilder: (context, index) { - final MapEntry(key: date, value: group) = grouped[index]; - - final children = [Text(date)]; - - for (final time in group) { - final isSelected = time.value == currentTemperatureTime; - - children.add( - ValueListenableBuilder( - valueListenable: manager.isLoading, - builder: (context, isLoading, child) { - return FilterChip( - selected: isSelected, - showCheckmark: !isLoading, - label: Text(time.time), - side: BorderSide( - color: isSelected ? context.colors.primary : context.colors.outlineVariant, - ), - avatar: isSelected && isLoading ? const LoadingIcon() : null, - onSelected: - isLoading - ? null - : (selected) { - if (!selected) return; - manager.setTemperatureTime(time.value); - }, - ); - }, - ), - ); - } - - children.add( - const Padding( - padding: EdgeInsets.only(right: 8), - child: VerticalDivider(width: 16, indent: 8, endIndent: 8), - ), + return Stack( + children: [ + MorphingSheet( + title: '氣溫'.i18n, + borderRadius: BorderRadius.circular(16), + elevation: 4, + partialBuilder: (context, controller, sheetController) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Selector>( + selector: (context, model) => model.temperature, + builder: (context, temperature, header) { + final times = temperature.map((time) { + final t = time.toSimpleDateTimeString().split(' '); + return (date: t[0], time: t[1], value: time); + }); + final grouped = times.groupListsBy((time) => time.date).entries.toList(); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + header!, + SizedBox( + height: kMinInteractiveDimension, + child: ValueListenableBuilder( + valueListenable: manager.currentTemperatureTime, + builder: (context, currentTemperatureTime, child) { + return ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 16), + scrollDirection: Axis.horizontal, + physics: const AlwaysScrollableScrollPhysics(), + itemCount: grouped.length, + itemBuilder: (context, index) { + final MapEntry(key: date, value: group) = grouped[index]; + + final children = [Text(date)]; + + for (final time in group) { + final isSelected = time.value == currentTemperatureTime; + + children.add( + ValueListenableBuilder( + valueListenable: manager.isLoading, + builder: (context, isLoading, child) { + return FilterChip( + selected: isSelected, + showCheckmark: !isLoading, + label: Text(time.time), + side: BorderSide( + color: isSelected ? context.colors.primary : context.colors.outlineVariant, + ), + avatar: isSelected && isLoading ? const LoadingIcon() : null, + onSelected: + isLoading + ? null + : (selected) { + if (!selected) return; + manager.setTemperatureTime(time.value); + }, + ); + }, + ), + ); + } + + children.add( + const Padding( + padding: EdgeInsets.only(right: 8), + child: VerticalDivider(width: 16, indent: 8, endIndent: 8), + ), + ); + + return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: children); + }, ); - - return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: children); }, - ); - }, - ), + ), + ), + ], + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + spacing: 8, + children: [ + const Icon(Symbols.thermostat_rounded, size: 24), + Text('氣溫'.i18n, style: context.textTheme.titleMedium), + ], ), - ], - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - spacing: 8, - children: [ - const Icon(Symbols.thermostat_rounded, size: 24), - Text('氣溫'.i18n, style: context.textTheme.titleMedium), - ], + ), + ), + ); + }, + ), + Positioned( + top: 24 + 48 + 16, + left: 24, + child: SafeArea( + child: BlurredContainer( + elevation: 4, + shadowColor: context.colors.shadow.withValues(alpha: 0.4), + child: Selector( + selector: (context, model) => model.useFahrenheit, + builder: (context, useFahrenheit, child) { + return ColorLegend( + reverse: true, + unit: useFahrenheit ? '℉' : '℃', + appendUnit: true, + items: [ + ColorLegendItem(color: const Color(0xff4d4e51), value: useFahrenheit ? -20.asFahrenheit : -20), + ColorLegendItem(color: const Color(0xff0000ff), value: useFahrenheit ? -10.asFahrenheit : -10), + ColorLegendItem(color: const Color(0xff6495ED), value: useFahrenheit ? 0.asFahrenheit : 0), + ColorLegendItem(color: const Color(0xff95d07e), value: useFahrenheit ? 10.asFahrenheit : 10), + ColorLegendItem(color: const Color(0xfff6e78b), value: useFahrenheit ? 20.asFahrenheit : 20), + ColorLegendItem(color: const Color(0xffff4500), value: useFahrenheit ? 30.asFahrenheit : 30), + ColorLegendItem(color: const Color(0xff8B0000), value: useFahrenheit ? 40.asFahrenheit : 40), + ], + ); + }, ), ), ), - ); - }, + ), + ], ); } } diff --git a/lib/app/map/_lib/managers/tsunami.dart b/lib/app/map/_lib/managers/tsunami.dart index 3156308f6..c0b4154b4 100644 --- a/lib/app/map/_lib/managers/tsunami.dart +++ b/lib/app/map/_lib/managers/tsunami.dart @@ -142,7 +142,7 @@ class _TsunamiMapLayerSheetState extends State { } if (Platform.isIOS && (Global.preference.getBool('auto-location') ?? false)) { - await getSavedLocation(); + await updateSavedLocationIOS(); } userLat = Global.preference.getDouble('user-lat') ?? 0.0; userLon = Global.preference.getDouble('user-lon') ?? 0.0; @@ -272,7 +272,7 @@ class _TsunamiMapLayerSheetState extends State { textColor: '#ffffff', textHaloColor: '#000000', textHaloWidth: 1, - textFont: ['Noto Sans Regular'], + textFont: ['Noto Sans TC Bold'], textOffset: [ Expressions.literal, [0, 3.5], diff --git a/lib/app/map/_lib/managers/wind.dart b/lib/app/map/_lib/managers/wind.dart index 3c6452c83..9c0c2e969 100644 --- a/lib/app/map/_lib/managers/wind.dart +++ b/lib/app/map/_lib/managers/wind.dart @@ -1,23 +1,26 @@ +import 'package:flutter/material.dart'; + import 'package:collection/collection.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/api/exptech.dart'; import 'package:dpip/api/model/weather/weather.dart'; import 'package:dpip/app/map/_lib/manager.dart'; import 'package:dpip/app/map/_lib/utils.dart'; +import 'package:dpip/app/map/_widgets/map_legend.dart'; import 'package:dpip/core/i18n.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/models/data.dart'; -import 'package:dpip/utils/constants.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/string.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/log.dart'; +import 'package:dpip/widgets/blurred_container.dart'; import 'package:dpip/widgets/map/map.dart'; import 'package:dpip/widgets/sheet/morphing_sheet.dart'; import 'package:dpip/widgets/ui/loading_icon.dart'; -import 'package:flutter/material.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; class WindData { final double latitude; @@ -41,6 +44,8 @@ class WindMapLayerManager extends MapLayerManager { final currentWindTime = ValueNotifier(GlobalProviders.data.wind.firstOrNull); final isLoading = ValueNotifier(false); + DateTime? _lastFetchTime; + Function(String)? onTimeChanged; Future setWindTime(String time) async { @@ -54,8 +59,6 @@ class WindMapLayerManager extends MapLayerManager { await setup(); onTimeChanged?.call(time); - - TalkerManager.instance.info('Updated Wind data time to "$time"'); } catch (e, s) { TalkerManager.instance.error('WindMapLayerManager.setWindTime', e, s); } finally { @@ -63,18 +66,23 @@ class WindMapLayerManager extends MapLayerManager { } } + Future _fetchData() async { + final windList = (await ExpTech().getWeatherList()).reversed.toList(); + if (!context.mounted) return; + + GlobalProviders.data.setWind(windList); + currentWindTime.value ??= windList.first; + _lastFetchTime = DateTime.now(); + } + @override Future setup() async { if (didSetup) return; - try { - if (GlobalProviders.data.wind.isEmpty) { - final windList = (await ExpTech().getWeatherList()).reversed.toList(); - if (!context.mounted) return; + final colors = context.colors; - GlobalProviders.data.setWind(windList); - currentWindTime.value = windList.first; - } + try { + if (GlobalProviders.data.wind.isEmpty) await _fetchData(); final time = currentWindTime.value; @@ -107,23 +115,60 @@ class WindMapLayerManager extends MapLayerManager { final properties = GeojsonSourceProperties(data: data); await controller.addSource(sourceId, properties); - TalkerManager.instance.info('Added Source "$sourceId"'); if (!context.mounted) return; } if (!isLayerExists) { + // arrows final properties = SymbolLayerProperties( iconImage: [Expressions.get, 'icon'], - iconSize: kSymbolIconSize, + iconSize: [ + Expressions.interpolate, + ['linear'], + [Expressions.zoom], + 5, + 0.1, + 15, + 0.8, + ], iconRotate: [Expressions.get, 'wind_direction'], + iconOpacity: 0.75, iconAllowOverlap: true, iconIgnorePlacement: true, visibility: visible ? 'visible' : 'none', ); + // labels + final properties2 = SymbolLayerProperties( + textField: [ + Expressions.concat, + [Expressions.get, 'name'], + '\n', + [ + Expressions.concat, + [Expressions.get, 'wind_speed'], + 'm/s', + ], + ], + textSize: 10, + textColor: colors.onSurfaceVariant.toHexStringRGB(), + textHaloColor: colors.outlineVariant.toHexStringRGB(), + textHaloWidth: 1, + textFont: ['Noto Sans TC Bold'], + textOffset: [0, 2], + textAnchor: 'top', + visibility: visible ? 'visible' : 'none', + ); + await controller.addLayer(sourceId, layerId, properties, belowLayerId: BaseMapLayerIds.userLocation); - TalkerManager.instance.info('Added Layer "$layerId"'); + await controller.addLayer( + sourceId, + '$layerId-label', + properties2, + belowLayerId: BaseMapLayerIds.userLocation, + minzoom: 10, + ); } if (isSourceExists && isLayerExists) return; @@ -142,7 +187,7 @@ class WindMapLayerManager extends MapLayerManager { try { await controller.setLayerVisibility(layerId, false); - TalkerManager.instance.info('Hiding Layer "$layerId"'); + await controller.setLayerVisibility('$layerId-label', false); visible = false; } catch (e, s) { @@ -158,9 +203,11 @@ class WindMapLayerManager extends MapLayerManager { try { await controller.setLayerVisibility(layerId, true); - TalkerManager.instance.info('Showing Layer "$layerId"'); + await controller.setLayerVisibility('$layerId-label', true); visible = true; + + if (_lastFetchTime == null || DateTime.now().difference(_lastFetchTime!).inMinutes > 5) await _fetchData(); } catch (e, s) { TalkerManager.instance.error('WindMapLayerManager.show', e, s); } @@ -173,10 +220,9 @@ class WindMapLayerManager extends MapLayerManager { final sourceId = MapSourceIds.wind(currentWindTime.value); await controller.removeLayer(layerId); - TalkerManager.instance.info('Removed Layer "$layerId"'); + await controller.removeLayer('$layerId-label'); await controller.removeSource(sourceId); - TalkerManager.instance.info('Removed Source "$sourceId"'); } catch (e, s) { TalkerManager.instance.error('WindMapLayerManager.dispose', e, s); } @@ -195,97 +241,136 @@ class WindMapLayerSheet extends StatelessWidget { @override Widget build(BuildContext context) { - return MorphingSheet( - title: '風向/風速'.i18n, - borderRadius: BorderRadius.circular(16), - elevation: 4, - partialBuilder: (context, controller, sheetController) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Selector>( - selector: (context, model) => model.wind, - builder: (context, wind, child) { - final times = wind.map((time) { - final t = time.toSimpleDateTimeString(context).split(' '); - return (date: t[0], time: t[1], value: time); - }); - final grouped = times.groupListsBy((time) => time.date).entries.toList(); - - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - spacing: 8, - children: [ - const Icon(Symbols.wind_power_rounded, size: 24), - Text('風向/風速'.i18n, style: context.textTheme.titleMedium), - ], - ), - ), - SizedBox( - height: kMinInteractiveDimension, - child: ValueListenableBuilder( - valueListenable: manager.currentWindTime, - builder: (context, currentWindTime, child) { - return ListView.builder( - padding: const EdgeInsets.symmetric(horizontal: 16), - scrollDirection: Axis.horizontal, - physics: const AlwaysScrollableScrollPhysics(), - itemCount: grouped.length, - itemBuilder: (context, index) { - final MapEntry(key: date, value: group) = grouped[index]; - - final children = [Text(date)]; - - for (final time in group) { - final isSelected = time.value == currentWindTime; - - children.add( - ValueListenableBuilder( - valueListenable: manager.isLoading, - builder: (context, isLoading, child) { - return FilterChip( - selected: isSelected, - showCheckmark: !isLoading, - label: Text(time.time), - side: BorderSide( - color: isSelected ? context.colors.primary : context.colors.outlineVariant, - ), - avatar: isSelected && isLoading ? const LoadingIcon() : null, - onSelected: - isLoading - ? null - : (selected) { - if (!selected) return; - manager.setWindTime(time.value); - }, - ); - }, - ), - ); - } - - children.add( - const Padding( - padding: EdgeInsets.only(right: 8), - child: VerticalDivider(width: 16, indent: 8, endIndent: 8), - ), + return Stack( + children: [ + MorphingSheet( + title: '風向/風速'.i18n, + borderRadius: BorderRadius.circular(16), + elevation: 4, + partialBuilder: (context, controller, sheetController) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Selector>( + selector: (context, model) => model.wind, + builder: (context, wind, child) { + final times = wind.map((time) { + final t = time.toSimpleDateTimeString().split(' '); + return (date: t[0], time: t[1], value: time); + }); + final grouped = times.groupListsBy((time) => time.date).entries.toList(); + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + spacing: 8, + children: [ + const Icon(Symbols.wind_power_rounded, size: 24), + Text('風向/風速'.i18n, style: context.textTheme.titleMedium), + ], + ), + ), + SizedBox( + height: kMinInteractiveDimension, + child: ValueListenableBuilder( + valueListenable: manager.currentWindTime, + builder: (context, currentWindTime, child) { + return ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 16), + scrollDirection: Axis.horizontal, + physics: const AlwaysScrollableScrollPhysics(), + itemCount: grouped.length, + itemBuilder: (context, index) { + final MapEntry(key: date, value: group) = grouped[index]; + + final children = [Text(date)]; + + for (final time in group) { + final isSelected = time.value == currentWindTime; + + children.add( + ValueListenableBuilder( + valueListenable: manager.isLoading, + builder: (context, isLoading, child) { + return FilterChip( + selected: isSelected, + showCheckmark: !isLoading, + label: Text(time.time), + side: BorderSide( + color: isSelected ? context.colors.primary : context.colors.outlineVariant, + ), + avatar: isSelected && isLoading ? const LoadingIcon() : null, + onSelected: + isLoading + ? null + : (selected) { + if (!selected) return; + manager.setWindTime(time.value); + }, + ); + }, + ), + ); + } + + children.add( + const Padding( + padding: EdgeInsets.only(right: 8), + child: VerticalDivider(width: 16, indent: 8, endIndent: 8), + ), + ); + + return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: children); + }, ); - - return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: children); }, - ); - }, - ), + ), + ), + ], + ); + }, + ), + ); + }, + ), + Positioned( + top: 24 + 48 + 16, + left: 24, + child: SafeArea( + child: BlurredContainer( + elevation: 4, + shadowColor: context.colors.shadow.withValues(alpha: 0.4), + child: Legend( + unit: 'm/s', + items: [ + LegendItem( + icon: const OutlinedIcon(Symbols.navigation_rounded, fill: Color(0xffffffff), size: 20), + label: '0.1 - 3.3', + ), + LegendItem( + icon: const OutlinedIcon(Symbols.navigation_rounded, fill: Color(0xff03fff0), size: 20), + label: '3.4 - 7.9', + ), + LegendItem( + icon: const OutlinedIcon(Symbols.navigation_rounded, fill: Color(0xff0385ff), size: 20), + label: '8.0 - 13.8', + ), + LegendItem( + icon: const OutlinedIcon(Symbols.navigation_rounded, fill: Color(0xff8000ff), size: 20), + label: '13.9 - 32.6', + ), + LegendItem( + icon: const OutlinedIcon(Symbols.navigation_rounded, fill: Color(0xffff006b), size: 20), + label: '≥ 32.7', ), ], - ); - }, + ), + ), ), - ); - }, + ), + ], ); } } diff --git a/lib/app/map/_widgets/layer_toggle_sheet.dart b/lib/app/map/_widgets/layer_toggle_sheet.dart index eb6fae021..f659a4afd 100644 --- a/lib/app/map/_widgets/layer_toggle_sheet.dart +++ b/lib/app/map/_widgets/layer_toggle_sheet.dart @@ -109,7 +109,7 @@ class _LayerToggleSheetState extends State { runSpacing: 8, children: [ LayerToggle( - label: '線條'.i18n, + label: '簡單'.i18n, checked: _currentBaseMap == BaseMapType.exptech, onChanged: (_) => _setBaseMap(BaseMapType.exptech), ), @@ -131,17 +131,17 @@ class _LayerToggleSheetState extends State { runSpacing: 8, children: [ LayerToggle( - label: '強震監視器'.i18n, + label: '監視器'.i18n, checked: _activeLayers.contains(MapLayer.monitor), onChanged: (checked) => _toggleLayer(MapLayer.monitor, checked), ), LayerToggle( - label: '地震報告'.i18n, + label: '報告'.i18n, checked: _activeLayers.contains(MapLayer.report), onChanged: (checked) => _toggleLayer(MapLayer.report, checked), ), LayerToggle( - label: '海嘯資訊'.i18n, + label: '海嘯'.i18n, checked: _activeLayers.contains(MapLayer.tsunami), onChanged: null, // (checked) => _toggleLayer(MapLayer.tsunami, checked), ), diff --git a/lib/app/map/_widgets/map_legend.dart b/lib/app/map/_widgets/map_legend.dart new file mode 100644 index 000000000..5bbf23df2 --- /dev/null +++ b/lib/app/map/_widgets/map_legend.dart @@ -0,0 +1,203 @@ +import 'package:flutter/material.dart'; + +import 'package:collection/collection.dart'; +import 'package:i18n_extension/i18n_extension.dart'; + +import 'package:dpip/core/i18n.dart'; +import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/widgets/layout.dart'; + +class ColorLegendItem { + final Color color; + final String? label; + final num value; + final bool blendHead; + final bool blendTail; + final bool hidden; + + ColorLegendItem({ + required this.color, + required this.value, + this.label, + this.blendHead = true, + this.blendTail = true, + this.hidden = false, + }); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + + if (other is ColorLegendItem) { + return color == other.color && + value == other.value && + label == other.label && + blendHead == other.blendHead && + blendTail == other.blendTail && + hidden == other.hidden; + } + + return false; + } + + @override + int get hashCode => Object.hash(color, value, blendHead, blendTail, hidden); +} + +class ColorLegend extends StatelessWidget { + final List items; + final bool reverse; + final String? unit; + final bool appendUnit; + + const ColorLegend({super.key, required this.items, this.reverse = false, this.appendUnit = false, this.unit}); + + @override + Widget build(BuildContext context) { + final items = reverse ? this.items.reversed.toList() : this.items; + final visibleItems = items.where((item) => !item.hidden).toList(); + + final children = + items.mapIndexed((index, item) { + if (item.hidden) return const SizedBox.shrink(); + + final visibleIndex = visibleItems.indexOf(item); + + final previous = index == 0 ? null : items.elementAtOrNull(index - 1); + final next = items.elementAtOrNull(index + 1); + + final headColor = + item.blendHead + ? (previous != null + ? Color.alphaBlend(item.color.withValues(alpha: 0.5), previous.color) + : item.color) + : item.color; + final tailColor = + item.blendTail + ? (next != null ? Color.alphaBlend(item.color.withValues(alpha: 0.5), next.color) : item.color) + : item.color; + + return IntrinsicHeight( + child: Layout.row.stretch[6]( + children: [ + if (!item.blendHead && !item.blendTail) + ColoredBox(color: item.color) + else + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [headColor, item.color, tailColor], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + borderRadius: + visibleIndex == 0 + ? const BorderRadius.vertical(top: Radius.circular(8)) + : (visibleIndex + 1) == visibleItems.length + ? const BorderRadius.vertical(bottom: Radius.circular(8)) + : null, + ), + width: 8, + ), + RichText( + text: TextSpan( + children: [ + TextSpan(text: item.label ?? '${item.value}'), + if (unit != null && appendUnit) + TextSpan(text: ' $unit', style: TextStyle(color: context.colors.outline)), + ], + style: context.textTheme.labelSmall?.copyWith( + color: context.colors.onSurfaceVariant, + fontFeatures: const [FontFeature.tabularFigures()], + ), + ), + ), + ], + ), + ); + }).toList(); + + return Layout.col.left[2]( + children: [ + Layout.col.left(children: children), + if (unit != null && !appendUnit) + Text( + '單位:{unit}'.i18n.args({'unit': unit!}), + style: context.textTheme.labelSmall?.copyWith(color: context.colors.onSurfaceVariant), + ), + ], + ); + } +} + +class LegendItem { + final Widget icon; + final String label; + + LegendItem({required this.icon, required this.label}); +} + +class Legend extends StatelessWidget { + final List items; + final bool reverse; + final String? unit; + final bool appendUnit; + + const Legend({super.key, required this.items, this.reverse = false, this.appendUnit = false, this.unit}); + + @override + Widget build(BuildContext context) { + final items = reverse ? this.items.reversed.toList() : this.items; + + final children = + items.map((item) { + return Layout.row.left[2]( + children: [ + item.icon, + RichText( + text: TextSpan( + children: [ + TextSpan(text: item.label), + if (unit != null && appendUnit) + TextSpan(text: ' $unit', style: TextStyle(color: context.colors.outline)), + ], + style: context.textTheme.labelSmall?.copyWith( + color: context.colors.onSurfaceVariant, + fontFeatures: const [FontFeature.tabularFigures()], + ), + ), + ), + ], + ); + }).toList(); + + return Layout.col.left[2]( + children: [ + Layout.col.left(children: children), + if (unit != null && !appendUnit) + Text( + '單位:{unit}'.i18n.args({'unit': unit!}), + style: context.textTheme.labelSmall?.copyWith(color: context.colors.onSurfaceVariant), + ), + ], + ); + } +} + +class OutlinedIcon extends StatelessWidget { + final IconData icon; + final Color? fill; + final Color? stroke; + final double? size; + + const OutlinedIcon(this.icon, {super.key, this.fill, this.stroke, this.size}); + + @override + Widget build(BuildContext context) { + return Stack( + children: [Icon(icon, fill: 1, color: fill, size: size), Icon(icon, fill: 0, color: stroke, size: size)], + ); + } +} diff --git a/lib/app/map/page.dart b/lib/app/map/page.dart index f051cd207..1637bdc2d 100644 --- a/lib/app/map/page.dart +++ b/lib/app/map/page.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:dpip/utils/extensions/maplibre.dart'; import 'package:flutter/material.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; @@ -223,32 +224,10 @@ class _MapPageState extends State with TickerProviderStateMixin { setState(() => _activeLayers = newLayers); } - void _hideBaseMapLayers() { - _controller.setLayerVisibility(BaseMapLayerIds.exptechGlobalFill, false); - _controller.setLayerVisibility(BaseMapLayerIds.exptechTownFill, false); - _controller.setLayerVisibility(BaseMapLayerIds.exptechCountyFill, false); - _controller.setLayerVisibility(BaseMapLayerIds.osmGlobalRaster, false); - _controller.setLayerVisibility(BaseMapLayerIds.googleGlobalRaster, false); - } - Future setBaseMapType(BaseMapType baseMapType) async { if (!mounted) return; - _hideBaseMapLayers(); - - switch (baseMapType) { - case BaseMapType.exptech: - await _controller.setLayerVisibility(BaseMapLayerIds.exptechGlobalFill, true); - await _controller.setLayerVisibility(BaseMapLayerIds.exptechTownFill, true); - await _controller.setLayerVisibility(BaseMapLayerIds.exptechCountyFill, true); - await _controller.setLayerVisibility(BaseMapLayerIds.exptechCountyOutline, true); - - case BaseMapType.osm: - await _controller.setLayerVisibility(BaseMapLayerIds.osmGlobalRaster, true); - - case BaseMapType.google: - await _controller.setLayerVisibility(BaseMapLayerIds.googleGlobalRaster, true); - } + await _controller.setBaseMap(baseMapType); setState(() => _baseMapType = baseMapType); } @@ -269,6 +248,14 @@ class _MapPageState extends State with TickerProviderStateMixin { void onMapCreated(MapLibreMapController controller) { setState(() => _controller = controller); + } + + void onStyleLoaded() { + final controller = _controller; + + for (final manager in _managers.values) { + manager.dispose(); + } _managers[MapLayer.monitor] = MonitorMapLayerManager(context, controller); _managers[MapLayer.report] = ReportMapLayerManager(context, controller, initialReportId: widget.options?.reportId); @@ -283,7 +270,6 @@ class _MapPageState extends State with TickerProviderStateMixin { _setupWeatherLayerTimeSync(); - setBaseMapType(_baseMapType); setLayers(_activeLayers); } @@ -299,7 +285,7 @@ class _MapPageState extends State with TickerProviderStateMixin { return Scaffold( body: Stack( children: [ - DpipMap(onMapCreated: onMapCreated, tiltGesturesEnabled: true), + DpipMap(baseMapType: _baseMapType, onMapCreated: onMapCreated, onStyleLoadedCallback: onStyleLoaded), PositionedLayerButton( activeLayers: _activeLayers, currentBaseMap: _baseMapType, diff --git a/lib/app/settings/donate/page.dart b/lib/app/settings/donate/page.dart index 05da71c94..f4aae7514 100644 --- a/lib/app/settings/donate/page.dart +++ b/lib/app/settings/donate/page.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:dpip/core/i18n.dart'; +import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/product_detail.dart'; import 'package:dpip/utils/functions.dart'; import 'package:dpip/widgets/list/list_section.dart'; @@ -10,6 +11,7 @@ import 'package:dpip/widgets/list/list_tile.dart'; import 'package:flutter/material.dart'; import 'package:i18n_extension/i18n_extension.dart'; import 'package:in_app_purchase/in_app_purchase.dart'; +import 'package:material_symbols_icons/symbols.dart'; import 'package:url_launcher/url_launcher.dart'; class SettingsDonatePage extends StatefulWidget { @@ -23,6 +25,9 @@ class SettingsDonatePage extends StatefulWidget { class _SettingsDonatePageState extends State { bool isPending = false; + String? processingProductId; + final Set purchasedProductIds = {}; + final _refreshIndicatorKey = GlobalKey(); Completer> products = Completer(); @@ -30,7 +35,10 @@ class _SettingsDonatePageState extends State { StreamSubscription>? subscription; Future refresh() async { - setState(() => products = Completer>()); + setState(() { + products = Completer>(); + purchasedProductIds.clear(); + }); final isAvailable = await InAppPurchase.instance.isAvailable(); @@ -64,6 +72,17 @@ class _SettingsDonatePageState extends State { } void onPurchaseUpdate(List purchaseDetailsList) { + bool hasAnyPending = purchaseDetailsList.any((detail) => detail.status == PurchaseStatus.pending); + + if (mounted) { + setState(() { + isPending = hasAnyPending; + if (!hasAnyPending) { + processingProductId = null; + } + }); + } + for (final purchaseDetails in purchaseDetailsList) { switch (purchaseDetails.status) { case PurchaseStatus.purchased: @@ -71,16 +90,26 @@ class _SettingsDonatePageState extends State { if (purchaseDetails.pendingCompletePurchase) { InAppPurchase.instance.completePurchase(purchaseDetails); } - setState(() => isPending = false); + if (mounted) { + setState(() { + purchasedProductIds.add(purchaseDetails.productID); + }); + } + break; case PurchaseStatus.error: case PurchaseStatus.canceled: if (purchaseDetails.pendingCompletePurchase) { InAppPurchase.instance.completePurchase(purchaseDetails); } - setState(() => isPending = false); + break; case PurchaseStatus.pending: + if (processingProductId == null) { + setState(() { + processingProductId = purchaseDetails.productID; + }); + } break; } } @@ -129,10 +158,9 @@ class _SettingsDonatePageState extends State { Padding( padding: const EdgeInsets.all(24), child: Text( - 'DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!'.i18n, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, // 調整顏色,使其顯眼 - ), + 'DPIP 作為一款致力於提供即時地震資訊的 App,目前並無廣告或其他盈利模式。為了維持高品質服務,我們需要承擔伺服器運行、地震數據獲取與傳輸、以及後續功能開發與維護的成本。\n\n您在下方所選的每一份支持,都將直接用於支付這些營運費用,幫助 DPIP 持續穩定地為您提供服務。感謝您的理解與慷慨!' + .i18n, + style: context.textTheme.bodyMedium?.copyWith(color: context.colors.onSurfaceVariant), textAlign: TextAlign.justify, ), ), @@ -146,14 +174,44 @@ class _SettingsDonatePageState extends State { product.title.contains('(') ? product.title.substring(0, product.title.indexOf('(')).trim() : product.title, - subtitle: Text(product.description), - trailing: Text('{price}/月'.i18n.args({'price': product.price})), - onTap: () { - if (isPending) return; - setState(() => isPending = true); - final purchaseParam = PurchaseParam(productDetails: product); - InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam); - }, + titleStyle: + (processingProductId != null && processingProductId != product.id) + ? TextStyle(color: context.theme.disabledColor) + : const TextStyle(fontWeight: FontWeight.bold), + subtitle: Text( + product.description, + style: TextStyle( + color: + (processingProductId != null && processingProductId != product.id) + ? context.theme.disabledColor + : context.textTheme.bodySmall?.color, + ), + ), + trailing: + (purchasedProductIds.contains(product.id)) + ? Icon(Symbols.check_rounded, color: context.colors.primary) + : (processingProductId == product.id) + ? const CircularProgressIndicator.adaptive() + : Text( + '{price}/月'.i18n.args({'price': product.price}), + style: TextStyle( + color: + (processingProductId != null && processingProductId != product.id) + ? context.theme.disabledColor + : context.textTheme.bodyMedium?.color, + ), + ), + onTap: + isPending || purchasedProductIds.contains(product.id) + ? null + : () { + setState(() { + isPending = true; + processingProductId = product.id; + }); + final purchaseParam = PurchaseParam(productDetails: product); + InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam); + }, ), ], ), @@ -167,14 +225,42 @@ class _SettingsDonatePageState extends State { product.title.contains('(') ? product.title.substring(0, product.title.indexOf('(')).trim() : product.title, - subtitle: Text(product.description), - trailing: Text(product.price), - onTap: () { - if (isPending) return; - setState(() => isPending = true); - final purchaseParam = PurchaseParam(productDetails: product); - InAppPurchase.instance.buyConsumable(purchaseParam: purchaseParam); - }, + titleStyle: + (processingProductId != null && processingProductId != product.id) + ? TextStyle(color: context.theme.disabledColor) + : const TextStyle(fontWeight: FontWeight.bold), + subtitle: Text( + product.description, + style: TextStyle( + color: + (processingProductId != null && processingProductId != product.id) + ? context.theme.disabledColor + : context.textTheme.bodySmall?.color, + ), + ), + trailing: + (processingProductId == product.id) + ? const CircularProgressIndicator.adaptive() + : Text( + product.price, + style: TextStyle( + color: + (processingProductId != null && processingProductId != product.id) + ? context.theme.disabledColor + : context.textTheme.bodyMedium?.color, + ), + ), + onTap: + isPending + ? null + : () { + setState(() { + isPending = true; + processingProductId = product.id; + }); + final purchaseParam = PurchaseParam(productDetails: product); + InAppPurchase.instance.buyConsumable(purchaseParam: purchaseParam); + }, ), ], ), @@ -194,19 +280,16 @@ class _SettingsDonatePageState extends State { if (!available) { final storeName = Platform.isIOS ? 'App Store' : 'Google Play'; - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('無法連線至 {store},請稍後再試。'.i18n.args({'store': storeName})))); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('無法連線至 {store},請稍後再試。'.i18n.args({'store': storeName}))), + ); return; } InAppPurchase.instance.restorePurchases(); ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('正在恢復您購買的訂閱'.i18n))); }, - child: Text( - '恢復購買'.i18n, - style: const TextStyle( - decoration: TextDecoration.underline, - ), - ), + child: Text('恢復購買'.i18n, style: const TextStyle(decoration: TextDecoration.underline)), ), const SizedBox(height: 4), InkWell( diff --git a/lib/app/settings/location/page.dart b/lib/app/settings/location/page.dart index 1bdc150d9..01e9a48ae 100644 --- a/lib/app/settings/location/page.dart +++ b/lib/app/settings/location/page.dart @@ -1,10 +1,22 @@ import 'dart:io'; -import 'package:autostarter/autostarter.dart'; +import 'package:dpip/api/exptech.dart'; +import 'package:dpip/core/preference.dart'; +import 'package:dpip/utils/toast.dart'; +import 'package:dpip/widgets/ui/loading_icon.dart'; +import 'package:flutter/material.dart'; + import 'package:disable_battery_optimization/disable_battery_optimization.dart'; -import 'package:dpip/app/settings/location/select/%5Bcity%5D/page.dart'; +import 'package:go_router/go_router.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/app/settings/location/select/page.dart'; import 'package:dpip/core/i18n.dart'; +import 'package:dpip/core/providers.dart'; import 'package:dpip/core/service.dart'; import 'package:dpip/global.dart'; import 'package:dpip/models/settings/location.dart'; @@ -12,13 +24,6 @@ import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/log.dart'; import 'package:dpip/widgets/list/list_section.dart'; import 'package:dpip/widgets/list/list_tile.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:go_router/go_router.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:material_symbols_icons/symbols.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:provider/provider.dart'; final stateSettingsLocationView = _SettingsLocationPageState(); @@ -33,319 +38,168 @@ class SettingsLocationPage extends StatefulWidget { State createState() => _SettingsLocationPageState(); } -const platform = MethodChannel('com.exptech.dpip/location'); - class _SettingsLocationPageState extends State with WidgetsBindingObserver { PermissionStatus? notificationPermission; PermissionStatus? locationPermission; PermissionStatus? locationAlwaysPermission; - bool? autoStartPermission; - bool? batteryOptimizationPermission; - - Future requestLocationAlwaysPermission() async { - var status = await Permission.locationWhenInUse.status; - if (status.isDenied) { - status = await Permission.locationWhenInUse.request(); - } + bool autoStartPermission = true; + bool batteryOptimizationPermission = true; + + Future permissionStatusUpdate() async { + final values = await Future.wait([ + Permission.notification.status, + Permission.location.status, + Permission.locationAlways.status, + // if (Platform.isAndroid) Autostarter.checkAutoStartState(), + if (Platform.isAndroid) DisableBatteryOptimization.isBatteryOptimizationDisabled, + ]); - if (status.isPermanentlyDenied) { - openAppSettings(); - return false; - } + if (!mounted) return; - return status.isGranted; + setState(() { + notificationPermission = values[0] as PermissionStatus?; + locationPermission = values[1] as PermissionStatus?; + locationAlwaysPermission = values[2] as PermissionStatus?; + autoStartPermission = values[3] as bool? ?? true; + batteryOptimizationPermission = values[4] as bool? ?? true; + }); } - Future checkNotificationPermission() async { - final status = await Permission.notification.request(); - if (!mounted) return false; - - setState(() => notificationPermission = status); - - if (!status.isGranted) { - await showDialog( - context: context, - builder: (context) { - return AlertDialog( - icon: const Icon(Symbols.error), - title: const Text('無法取得通知權限'), - content: Text( - "'自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。'${status.isPermanentlyDenied ? '請您到應用程式設定中找到並允許「通知」權限後再試一次。' : ""}", + /// Shows a error dialog to the user with the given permission type. [type] can be either [Permission] or + /// `"auto-start"` + Future showPermissionDialog(dynamic type) async { + if (!mounted) return; + if (type is! Permission && type is! String) return; + + final title = switch (type) { + Permission.notification => '無法取得通知權限'.i18n, + Permission.location => '無法取得位置權限'.i18n, + Permission.locationAlways => '無法取得位置權限'.i18n, + 'auto-start' => '無法取得自啟動權限'.i18n, + 'battery-optimization' => '省電策略'.i18n, + _ => '無法取得權限'.i18n, + }; + + final content = switch (type) { + Permission.notification => '自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。請您到應用程式設定中找到並允許「通知」權限後再試一次。'.i18n, + Permission.location => '自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到並允許「位置」權限後再試一次。'.i18n, + Permission.locationAlways => + Platform.isIOS + ? '自動定位功能需要您永遠允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「永遠」後再試一次。'.i18n + : '自動定位功能需要您一律允許 DPIP 使用位置權限才能正常運作。請您到應用程式設定中找到位置權限設定並選擇「一律允許」後再試一次。'.i18n, + 'auto-start' => '為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。'.i18n, + 'battery-optimization' => '為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。'.i18n, + _ => '自動定位功能需要您允許 DPIP 使用權限才能正常運作。請您到應用程式設定中找到並允許「權限」後再試一次。'.i18n, + }; + + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + icon: const Icon(Symbols.error_rounded), + title: Text(title), + content: Text(content), + actionsAlignment: MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + child: Text('取消'.i18n), + onPressed: () { + Navigator.pop(context); + }, ), - actionsAlignment: MainAxisAlignment.spaceBetween, - actions: [ - TextButton( - child: const Text('取消'), - onPressed: () { - Navigator.pop(context); - }, - ), - if (status.isPermanentlyDenied) - FilledButton( - child: const Text('設定'), - onPressed: () { - openAppSettings(); - Navigator.pop(context); - }, - ) - else - FilledButton( - child: const Text('再試一次'), - onPressed: () { - checkNotificationPermission(); - Navigator.pop(context); - }, - ), - ], - ); - }, - ); + FilledButton( + child: Text('設定'.i18n), + onPressed: () { + openAppSettings(); + Navigator.pop(context); + }, + ), + ], + ); + }, + ); + } + Future requestPermissions() async { + if (!await Permission.notification.request().isGranted) { + TalkerManager.instance.warning('🧪 failed notification (NOTIFICATION) permission test'); + await showPermissionDialog(Permission.notification); return false; } - return true; - } - - Future checkLocationPermission() async { - final status = await Permission.location.request(); - if (!mounted) return false; - - setState(() => locationPermission = status); - - if (!status.isGranted) { - await showDialog( - context: context, - builder: (context) { - return AlertDialog( - icon: const Icon(Symbols.error), - title: const Text('無法取得位置權限'), - content: Text( - "'自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。'${status.isPermanentlyDenied ? '請您到應用程式設定中找到並允許「位置」權限後再試一次。' : ""}", - ), - actionsAlignment: MainAxisAlignment.spaceBetween, - actions: [ - TextButton( - child: const Text('取消'), - onPressed: () { - Navigator.pop(context); - }, - ), - if (status.isPermanentlyDenied) - FilledButton( - child: const Text('設定'), - onPressed: () { - openAppSettings(); - Navigator.pop(context); - }, - ) - else - FilledButton( - child: const Text('再試一次'), - onPressed: () { - checkLocationPermission(); - Navigator.pop(context); - }, - ), - ], - ); - }, - ); - + if (!await Permission.location.request().isGranted) { + TalkerManager.instance.warning('🧪 failed location (ACCESS_COARSE_LOCATION) permission test'); + showPermissionDialog(Permission.location); return false; } - return true; - } - - Future checkLocationAlwaysPermission() async { - final status = await Permission.locationAlways.status; - - setState(() => locationAlwaysPermission = status); - - if (status.isGranted) { - return true; - } else { - if (!mounted) return false; - final permissionType = Platform.isAndroid ? '一律允許' : '永遠'; - - final status = - await showDialog( - context: context, - builder: (context) { - return AlertDialog( - icon: const Icon(Symbols.my_location), - title: Text('$permissionType 位置權限'), - content: Text('為了獲得更好的自動定位體驗,您需要將位置權限提升至「$permissionType」以便讓 DPIP 在背景自動設定所在地資訊。'), - actionsAlignment: MainAxisAlignment.spaceBetween, - actions: [ - TextButton( - child: const Text('取消'), - onPressed: () { - Navigator.pop(context, false); - }, - ), - FilledButton( - child: const Text('確定'), - onPressed: () async { - final status = await Permission.locationAlways.request(); - - setState(() => locationAlwaysPermission = status); - - if (status.isPermanentlyDenied) { - openAppSettings(); - } - - if (!context.mounted) return; - - Navigator.pop(context, status.isGranted); - }, - ), - ], - ); - }, - ) ?? - false; - - return status; + if (!await Permission.locationWhenInUse.request().isGranted) { + TalkerManager.instance.warning('🧪 failed location when in use (ACCESS_FINE_LOCATION) permission test'); + showPermissionDialog(Permission.locationWhenInUse); + return false; } - } - - Future androidCheckAutoStartPermission(int num) async { - if (!Platform.isAndroid) return true; - try { - final bool? isAvailable = await Autostarter.isAutoStartPermissionAvailable(); - if (isAvailable == null || !isAvailable) return true; - - final bool? status = await Autostarter.checkAutoStartState(); - if (status == null || status) return true; - - if (!mounted) return true; - - final String contentText = - (num == 0) - ? '為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。' - : '為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。'; - - return await showDialog( - context: context, - builder: (context) { - return AlertDialog( - icon: const Icon(Symbols.my_location), - title: const Text('自啟動權限'), - content: Text(contentText), - actionsAlignment: MainAxisAlignment.spaceBetween, - actions: [ - TextButton( - child: const Text('取消'), - onPressed: () { - Navigator.pop(context, false); - }, - ), - FilledButton( - child: const Text('確定'), - onPressed: () async { - await Autostarter.getAutoStartPermission(newTask: true); - - if (!context.mounted) return; - Navigator.pop(context, false); - }, - ), - ], - ); - }, - ) ?? - false; - } catch (err) { - TalkerManager.instance.error(err); + if (!await Permission.locationAlways.request().isGranted) { + TalkerManager.instance.warning('🧪 failed location always (ACCESS_BACKGROUND_LOCATION) permission test'); + showPermissionDialog(Permission.locationAlways); return false; } - } - Future androidCheckBatteryOptimizationPermission(int num) async { if (!Platform.isAndroid) return true; - try { - final bool status = await DisableBatteryOptimization.isBatteryOptimizationDisabled ?? false; - if (status) return true; - - if (!mounted) return true; - - final String contentText = - (num == 0) - ? '為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。' - : '為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。'; - - return await showDialog( - context: context, - builder: (context) { - return AlertDialog( - icon: const Icon(Symbols.my_location), - title: const Text('省電策略'), - content: Text(contentText), - actionsAlignment: MainAxisAlignment.spaceBetween, - actions: [ - TextButton( - child: const Text('取消'), - onPressed: () { - Navigator.pop(context, false); - }, - ), - FilledButton( - child: const Text('確定'), - onPressed: () { - DisableBatteryOptimization.showDisableBatteryOptimizationSettings(); - Navigator.pop(context, false); - }, - ), - ], - ); - }, - ) ?? - false; - } catch (err) { - TalkerManager.instance.error(err); - return false; - } - } + autoStart: + { + // final available = await Autostarter.isAutoStartPermissionAvailable(); + // if (available == null) break autoStart; - Future toggleAutoLocation() async { - final isAuto = context.read().auto; + final status = await DisableBatteryOptimization.isAutoStartEnabled; + if (status == null || status) { + batteryOptimizationPermission = true; + break autoStart; + } - stopAndroidBackgroundService(); + await DisableBatteryOptimization.showEnableAutoStartSettings( + '自動啟動'.i18n, + '為了獲得更好的 DPIP 體驗,請依照步驟啟用自動啟動功能,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。'.i18n, + ); + } - if (!isAuto) { - final notification = await checkNotificationPermission(); - if (!notification) return; + batteryOptimization: + { + final status = await DisableBatteryOptimization.isBatteryOptimizationDisabled; + if (status == null || status) { + batteryOptimizationPermission = true; + break batteryOptimization; + } - final location = await checkLocationPermission(); - if (!location) return; + await DisableBatteryOptimization.showDisableBatteryOptimizationSettings(); + } - await checkLocationAlwaysPermission(); + manufacturerBatteryOptimization: + { + final status = await DisableBatteryOptimization.isManufacturerBatteryOptimizationDisabled; + if (status == null || status) break manufacturerBatteryOptimization; - final bool autoStart = await androidCheckAutoStartPermission(0); - autoStartPermission = autoStart; - if (!autoStart) return; + await DisableBatteryOptimization.showEnableAutoStartSettings( + '省電策略'.i18n, + '為了獲得更好的 DPIP 體驗,請依照步驟關閉省電策略,以便讓 DPIP 在背景能正常接收資訊以及更新所在地。'.i18n, + ); + } - final bool batteryOptimization = await androidCheckBatteryOptimizationPermission(0); - batteryOptimizationPermission = batteryOptimization; - if (!batteryOptimization) return; + setState(() {}); + return true; + } - if (!isAuto) { - startAndroidBackgroundService(shouldInitialize: false); - } - } + Future toggleAutoLocation(bool shouldEnable) async { + if (shouldEnable) { + if (!await requestPermissions()) return; - if (Platform.isIOS) { - await platform.invokeMethod('toggleLocation', {'isEnabled': !isAuto}).catchError((_) {}); + await LocationServiceManager.start(); + } else { + await LocationServiceManager.stop(); } - if (!mounted) return; - - context.read().setAuto(!isAuto); - context.read().setCode(null); - context.read().setLatLng(); + GlobalProviders.location.setAuto(shouldEnable); } @override @@ -355,60 +209,14 @@ class _SettingsLocationPageState extends State with Widget permissionStatusUpdate(); } - @override - void dispose() { - WidgetsBinding.instance.removeObserver(this); - super.dispose(); - } - @override void didChangeAppLifecycleState(AppLifecycleState state) { permissionStatusUpdate(); } - void permissionStatusUpdate() { - Permission.notification.status.then((value) { - setState(() { - notificationPermission = value; - }); - }); - Permission.location.status.then((value) { - setState(() { - locationPermission = value; - }); - }); - Permission.locationAlways.status.then((value) { - setState(() { - locationAlwaysPermission = value; - }); - }); - if (Platform.isAndroid) { - Future checkAutoStart() async { - final autoStart = await Autostarter.checkAutoStartState(); - if (mounted) { - setState(() { - autoStartPermission = autoStart ?? false; - }); - } - } - - Future checkBatteryOptimization() async { - final batteryOptimization = await DisableBatteryOptimization.isBatteryOptimizationDisabled; - if (mounted) { - setState(() { - batteryOptimizationPermission = batteryOptimization ?? false; - }); - } - } - - checkAutoStart(); - checkBatteryOptimization(); - } - } - @override Widget build(BuildContext context) { - final permissionType = Platform.isAndroid ? '一律允許' : '永遠'; + final permissionType = Platform.isAndroid ? '一律允許'.i18n : '永遠'.i18n; return ListView( padding: EdgeInsets.only(top: 8, bottom: 16 + context.padding.bottom), @@ -422,7 +230,7 @@ class _SettingsLocationPageState extends State with Widget title: '自動更新'.i18n, subtitle: Text('定期更新目前的所在地'.i18n), icon: Symbols.my_location_rounded, - trailing: Switch(value: auto, onChanged: (value) => toggleAutoLocation()), + trailing: Switch(value: auto, onChanged: toggleAutoLocation), ); }, ), @@ -455,11 +263,11 @@ class _SettingsLocationPageState extends State with Widget const SizedBox(width: 8), Expanded( child: Text( - '自動定位功能需要將位置權限提升至「$permissionType」以在背景使用。', + '自動定位功能需要將位置權限提升至「$permissionType」以在背景使用。'.i18n, style: TextStyle(color: context.colors.error), ), ), - TextButton(child: const Text('設定'), onPressed: () => openAppSettings()), + TextButton(child: Text('設定'.i18n), onPressed: () => openAppSettings()), ], ), ), @@ -488,8 +296,10 @@ class _SettingsLocationPageState extends State with Widget child: Icon(Symbols.warning_rounded, color: context.colors.error), ), const SizedBox(width: 8), - Expanded(child: Text('通知功能已被拒絕,請移至設定允許權限。', style: TextStyle(color: context.colors.error))), - TextButton(child: const Text('設定'), onPressed: () => openAppSettings()), + Expanded( + child: Text('通知功能已被拒絕,請移至設定允許權限。'.i18n, style: TextStyle(color: context.colors.error)), + ), + TextButton(child: Text('設定'.i18n), onPressed: () => openAppSettings()), ], ), ), @@ -497,51 +307,51 @@ class _SettingsLocationPageState extends State with Widget ); }, ), - if (Platform.isAndroid && false) + /* if (Platform.isAndroid) Selector( selector: (context, model) => model.auto, builder: (context, auto, child) { return Visibility( - visible: auto && !autoStartPermission!, + visible: auto && !autoStartPermission, maintainAnimation: true, maintainState: true, child: AnimatedOpacity( - opacity: auto && !autoStartPermission! ? 1 : 0, + opacity: auto && !autoStartPermission ? 1 : 0, curve: const Interval(0.2, 1, curve: Easing.standard), duration: Durations.medium2, child: SettingsListTextSection( icon: Symbols.warning_rounded, iconColor: context.colors.error, - content: '自啟動權限已被拒絕,請移至設定允許權限。', + content: '自啟動權限已被拒絕,請移至設定允許權限。'.i18n, contentColor: context.colors.error, trailing: TextButton( - child: const Text('設定'), + child: Text('設定'.i18n), onPressed: () => Autostarter.getAutoStartPermission(newTask: true), ), ), ), ); }, - ), - if (batteryOptimizationPermission != null && Platform.isAndroid) + ),*/ + if (Platform.isAndroid) Selector( selector: (context, model) => model.auto, builder: (context, auto, child) { return Visibility( - visible: auto && !batteryOptimizationPermission!, + visible: auto && !batteryOptimizationPermission, maintainAnimation: true, maintainState: true, child: AnimatedOpacity( - opacity: auto && !batteryOptimizationPermission! ? 1 : 0, + opacity: auto && !batteryOptimizationPermission ? 1 : 0, curve: const Interval(0.2, 1, curve: Easing.standard), duration: Durations.medium2, child: SettingsListTextSection( icon: Symbols.warning_rounded, iconColor: context.colors.error, - content: '省電策略已被拒絕,請移至設定允許權限。', + content: '省電策略已被拒絕,請移至設定允許權限。'.i18n, contentColor: context.colors.error, trailing: TextButton( - child: const Text('設定'), + child: Text('設定'.i18n), onPressed: () { DisableBatteryOptimization.showDisableBatteryOptimizationSettings(); }, @@ -551,129 +361,80 @@ class _SettingsLocationPageState extends State with Widget ); }, ), - ListSection( - title: '所在地'.i18n, - children: [ - Selector( - selector: (context, model) => (auto: model.auto, code: model.code), - builder: (context, data, child) { - final (:auto, :code) = data; - final city = Global.location[code]?.city; - - return ListSectionTile( - title: '直轄市/縣市'.i18n, - subtitle: Text(city ?? '尚未設定'.i18n), - icon: Symbols.location_city_rounded, - trailing: const Icon(Symbols.chevron_right_rounded), - enabled: !auto, - onTap: () async { - final bool autoStart = await androidCheckAutoStartPermission(1); - if (!autoStart) return; - - final bool batteryOptimization = await androidCheckBatteryOptimizationPermission(1); - if (!batteryOptimization) return; - - if (!context.mounted) return; - - context.push(SettingsLocationSelectPage.route); - }, - ); - }, - ), - Selector( - selector: (context, model) => (auto: model.auto, code: model.code), - builder: (context, data, child) { - final (:auto, :code) = data; - - final city = Global.location[code]?.city; - final town = Global.location[code]?.town; - - return ListSectionTile( - title: '鄉鎮市區'.i18n, - subtitle: Text(town ?? '尚未設定'.i18n), - icon: Symbols.forest_rounded, - trailing: const Icon(Symbols.chevron_right_rounded), - enabled: !auto && city != null, - onTap: () async { - if (city == null) return; - - final bool autoStart = await androidCheckAutoStartPermission(1); - if (!autoStart) return; - - final bool batteryOptimization = await androidCheckBatteryOptimizationPermission(1); - if (!batteryOptimization) return; - - if (!context.mounted) return; - - context.push(SettingsLocationSelectCityPage.route(city)); - }, + Consumer( + builder: (context, model, child) { + String? loadingCode; + + return StatefulBuilder( + builder: (context, setState) { + return ListSection( + title: '所在地'.i18n, + children: [ + ...model.favorited.map((code) { + final location = Global.location[code]!; + + final isCurrentLoading = loadingCode == code; + final isSelected = code == model.code; + + return ListSectionTile( + title: location.cityTownWithLevel, + subtitle: Text( + '$code・${location.lng.toStringAsFixed(2)}°E・${location.lat.toStringAsFixed(2)}°N', + ), + leading: + isCurrentLoading + ? const LoadingIcon() + : Icon(isSelected ? Symbols.check_rounded : null, color: context.colors.primary), + trailing: IconButton( + icon: const Icon(Symbols.delete_rounded), + color: context.colors.error, + onPressed: isCurrentLoading ? null : () => model.unfavorite(code), + ), + enabled: !model.auto && loadingCode == null, + onTap: + isSelected + ? null + : () async { + setState(() => loadingCode = code); + + try { + await ExpTech().updateDeviceLocation( + token: Preference.notifyToken, + coordinates: LatLng(location.lat, location.lng), + ); + + if (!context.mounted) return; + + model.setCode(code); + } catch (e, s) { + if (!context.mounted) return; + TalkerManager.instance.error('Failed to set location code', e, s); + showToast(context, ToastWidget.text('設定所在地時發生錯誤,請稍候再試一次。'.i18n)); + } + + setState(() => loadingCode = null); + }, + ); + }), + ListSectionTile( + title: '新增地點'.i18n, + icon: Symbols.add_circle_rounded, + enabled: loadingCode == null, + onTap: () => context.push(SettingsLocationSelectPage.route), + ), + ], ); }, - ), - ], + ); + }, ), - if (false && Platform.isAndroid) - Selector( - selector: (context, model) => (auto: model.auto, code: model.code), - builder: (context, data, child) { - final (:auto, :code) = data; - - return Visibility( - visible: !auto && code != null && !autoStartPermission!, - maintainAnimation: true, - maintainState: true, - child: AnimatedOpacity( - opacity: !auto && code != null && !autoStartPermission! ? 1 : 0, - curve: const Interval(0.2, 1, curve: Easing.standard), - duration: Durations.medium2, - child: SettingsListTextSection( - icon: Symbols.warning_rounded, - iconColor: context.colors.error, - content: '自啟動權限已被拒絕,請移至設定允許權限。', - contentColor: context.colors.error, - trailing: TextButton( - child: const Text('設定'), - onPressed: () async { - await Autostarter.getAutoStartPermission(newTask: true); - }, - ), - ), - ), - ); - }, - ), - if (batteryOptimizationPermission != null && Platform.isAndroid) - Selector( - selector: (context, model) => (auto: model.auto, code: model.code), - builder: (context, data, child) { - final (:auto, :code) = data; - - return Visibility( - visible: !auto && code != null && !batteryOptimizationPermission!, - maintainAnimation: true, - maintainState: true, - child: AnimatedOpacity( - opacity: !auto && code != null && !batteryOptimizationPermission! ? 1 : 0, - curve: const Interval(0.2, 1, curve: Easing.standard), - duration: Durations.medium2, - child: SettingsListTextSection( - icon: Symbols.warning_rounded, - iconColor: context.colors.error, - content: '省電策略已被拒絕,請移至設定允許權限。', - contentColor: context.colors.error, - trailing: TextButton( - child: const Text('設定'), - onPressed: () { - DisableBatteryOptimization.showDisableBatteryOptimizationSettings(); - Navigator.pop(context); - }, - ), - ), - ), - ); - }, - ), ], ); } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } } diff --git a/lib/app/settings/location/select/[city]/page.dart b/lib/app/settings/location/select/[city]/page.dart index e22bc68f8..6d60dd3e7 100644 --- a/lib/app/settings/location/select/[city]/page.dart +++ b/lib/app/settings/location/select/[city]/page.dart @@ -1,15 +1,16 @@ -import 'package:dpip/api/exptech.dart'; +import 'dart:collection'; + +import 'package:flutter/material.dart'; + +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/app/settings/location/page.dart'; -import 'package:dpip/core/preference.dart'; import 'package:dpip/global.dart'; import 'package:dpip/models/settings/location.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/widgets/list/list_section.dart'; import 'package:dpip/widgets/list/list_tile.dart'; -import 'package:dpip/widgets/ui/loading_icon.dart'; -import 'package:flutter/material.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; class SettingsLocationSelectCityPage extends StatefulWidget { final String city; @@ -23,11 +24,9 @@ class SettingsLocationSelectCityPage extends StatefulWidget { } class _SettingsLocationSelectCityPageState extends State { - String? loadingTown; - @override Widget build(BuildContext context) { - final towns = Global.location.entries.where((e) => e.value.city == widget.city).toList(); + final towns = Global.location.entries.where((e) => e.value.cityWithLevel == widget.city).toList(); return ListView( padding: EdgeInsets.only(top: 8, bottom: 16 + context.padding.bottom), @@ -35,41 +34,25 @@ class _SettingsLocationSelectCityPageState extends State( - selector: (context, model) => model.code, - builder: - (context, code, child) => ListSectionTile( - title: '${town.value.city} ${town.value.town}', - subtitle: Text( - '${town.key}・${town.value.lng.toStringAsFixed(2)}°E・${town.value.lat.toStringAsFixed(2)}°N', - ), - trailing: - loadingTown == town.key - ? const LoadingIcon() - : Icon(code == town.key ? Symbols.check_rounded : null), - enabled: loadingTown == null, - onTap: () async { - if (loadingTown != null) return; - - setState(() => loadingTown = town.key); - await ExpTech().updateDeviceLocation( - token: Preference.notifyToken, - lat: town.value.lat.toString(), - lng: town.value.lng.toString(), - ); - - if (!context.mounted) return; - setState(() => loadingTown = null); - - context.read().setCode(town.key); - context.read().setLatLng( - latitude: town.value.lat, - longitude: town.value.lng, - ); - context.popUntil(SettingsLocationPage.route); - }, - ), + for (final MapEntry(key: code, value: town) in towns) + Selector>( + selector: (context, model) => model.favorited, + builder: (context, favorited, child) { + final isFavorited = favorited.contains(code); + + return ListSectionTile( + title: town.cityTownWithLevel, + subtitle: Text('$code・${town.lng.toStringAsFixed(2)}°E・${town.lat.toStringAsFixed(2)}°N'), + trailing: isFavorited ? const Icon(Symbols.star_rounded, fill: 1) : null, + onTap: + isFavorited + ? null + : () { + context.read().favorite(code); + context.popUntil(SettingsLocationPage.route); + }, + ); + }, ), ], ), diff --git a/lib/app/settings/location/select/page.dart b/lib/app/settings/location/select/page.dart index ee8b70843..88991eafa 100644 --- a/lib/app/settings/location/select/page.dart +++ b/lib/app/settings/location/select/page.dart @@ -1,16 +1,17 @@ +import 'package:dpip/utils/extensions/string.dart'; +import 'package:flutter/material.dart'; + +import 'package:collection/collection.dart'; +import 'package:go_router/go_router.dart'; +import 'package:material_symbols_icons/material_symbols_icons.dart'; +import 'package:provider/provider.dart'; + import 'package:dpip/core/i18n.dart'; import 'package:dpip/global.dart'; import 'package:dpip/models/settings/location.dart'; import 'package:dpip/utils/extensions/build_context.dart'; -import 'package:dpip/utils/extensions/list.dart'; import 'package:dpip/widgets/list/list_section.dart'; import 'package:dpip/widgets/list/list_tile.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:material_symbols_icons/material_symbols_icons.dart'; -import 'package:provider/provider.dart'; - -final cities = Global.location.entries.map((e) => e.value.city).toSet().toList(); class SettingsLocationSelectPage extends StatelessWidget { const SettingsLocationSelectPage({super.key}); @@ -19,25 +20,35 @@ class SettingsLocationSelectPage extends StatelessWidget { @override Widget build(BuildContext context) { + final entries = Global.location.entries.toList(); + + final locations = + entries + .whereIndexed( + (index, e) => + index == + entries.indexWhere((v) => (v.value.city == e.value.city) && (v.value.cityLevel == e.value.cityLevel)), + ) + .toList(); + return ListView( padding: EdgeInsets.only(top: 8, bottom: 16 + context.padding.bottom), children: [ ListSection( title: '縣市'.i18n, children: [ - for (final city in cities) + for (final MapEntry(key: _, value: location) in locations) Selector( selector: (context, model) => model.code, builder: - (context, code, child) => ListSectionTile( - title: city, + (context, currentCode, child) => ListSectionTile( + title: location.cityWithLevel, trailing: const Icon(Symbols.chevron_right_rounded), subtitle: - code != null && - Global.location.entries.containsWhere((e) => e.value.city == city && e.key == code) + currentCode != null && location.cityWithLevel == currentCode.getLocation().cityWithLevel ? Text('目前所在地'.i18n) : null, - onTap: () => context.push('/settings/location/select/$city'), + onTap: () => context.push('/settings/location/select/${location.cityWithLevel}'), ), ), ], diff --git a/lib/app/settings/map/page.dart b/lib/app/settings/map/page.dart index bdc49a90c..d5757790a 100644 --- a/lib/app/settings/map/page.dart +++ b/lib/app/settings/map/page.dart @@ -53,7 +53,7 @@ class SettingsMapPage extends StatelessWidget { MapLayer.wind: '風向/風速'.i18n, }; final baseMapLabels = { - BaseMapType.exptech: '線條'.i18n, + BaseMapType.exptech: '簡單'.i18n, BaseMapType.osm: 'OpenStreetMap'.i18n, BaseMapType.google: 'Google'.i18n, }; @@ -100,17 +100,19 @@ class SettingsMapPage extends StatelessWidget { Layout.row.left[16]( children: [ Icon(Symbols.animation_rounded, weight: 600, color: context.colors.secondary), - Layout.col.left( - children: [ - Text( - '動畫幀率'.i18n, - style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold), - ), - Text( - '影響強震監視器的震波模擬動畫流暢度'.i18n, - style: context.textTheme.bodyMedium?.copyWith(color: context.colors.onSurfaceVariant), - ), - ], + Expanded( + child: Layout.col.left.min( + children: [ + Text( + '動畫幀率'.i18n, + style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold), + ), + Text( + '影響強震監視器的震波模擬動畫流暢度'.i18n, + style: context.textTheme.bodyMedium?.copyWith(color: context.colors.onSurfaceVariant), + ), + ], + ), ), ], ), diff --git a/lib/app/settings/notify/(3.weather)/evacuation/page.dart b/lib/app/settings/notify/(3.weather)/evacuation/page.dart index c1b211c68..d8085d450 100644 --- a/lib/app/settings/notify/(3.weather)/evacuation/page.dart +++ b/lib/app/settings/notify/(3.weather)/evacuation/page.dart @@ -30,8 +30,8 @@ class SettingsNotifyEvacuationPage extends StatelessWidget { ListSection( title: '音效測試'.i18n, children: [ - SoundListTile(title: '重大'.i18n, subtitle: Text('所在地(鄉鎮)發布避難警訊時'.i18n), type: 'evacuation_major-important-v2'), - SoundListTile(title: '一般'.i18n, subtitle: Text('所在地(鄉鎮)發布避難資訊時'.i18n), type: 'evacuation_minor-general-v2'), + SoundListTile(title: '重大'.i18n, subtitle: Text('所在地(鄉鎮)發布防災警訊時'.i18n), type: 'evacuation_major-important-v2'), + SoundListTile(title: '一般'.i18n, subtitle: Text('所在地(鄉鎮)發布防災資訊時'.i18n), type: 'evacuation_minor-general-v2'), ], ), SettingsListTextSection( diff --git a/lib/app/settings/notify/(3.weather)/thunderstorm/page.dart b/lib/app/settings/notify/(3.weather)/thunderstorm/page.dart index a9e979e50..27fc3eb3d 100644 --- a/lib/app/settings/notify/(3.weather)/thunderstorm/page.dart +++ b/lib/app/settings/notify/(3.weather)/thunderstorm/page.dart @@ -30,9 +30,14 @@ class SettingsNotifyThunderstormPage extends StatelessWidget { ListSection( title: '音效測試'.i18n, children: [ + SoundListTile( + title: '重大'.i18n, + subtitle: Text('所在地(鄉鎮)發布山區暴雨時'.i18n), + type: 'thunderstorm-important-v2', + ), SoundListTile( title: '一般'.i18n, - subtitle: Text('所在地(鄉鎮)發布雷雨即時訊息或\n山區暴雨時'.i18n), + subtitle: Text('所在地(鄉鎮)發布雷雨即時訊息時'.i18n), type: 'thunderstorm-general-v2', ), ], diff --git a/lib/app/settings/notify/(4.tsunami)/tsunami/page.dart b/lib/app/settings/notify/(4.tsunami)/tsunami/page.dart index 1cbf94721..5a698ddc8 100644 --- a/lib/app/settings/notify/(4.tsunami)/tsunami/page.dart +++ b/lib/app/settings/notify/(4.tsunami)/tsunami/page.dart @@ -30,8 +30,8 @@ class SettingsNotifyTsunamiPage extends StatelessWidget { ListSection( title: '音效測試'.i18n, children: [ - SoundListTile(title: '重大'.i18n, subtitle: Text('海嘯警報發布時\n沿海地區鄉鎮'.i18n), type: 'tsunami-important-v2'), - SoundListTile(title: '一般'.i18n, subtitle: Text('海嘯警報發布時\n上述除外地區'.i18n), type: 'tsunami-general-v2'), + SoundListTile(title: '重大'.i18n, subtitle: Text('海嘯警報發布時'.i18n), type: 'tsunami-important-v2'), + SoundListTile(title: '一般'.i18n, subtitle: Text('海嘯消息發布時'.i18n), type: 'tsunami-general-v2'), SoundListTile(title: '太平洋海嘯消息(無聲通知)'.i18n, subtitle: Text('太平洋海嘯消息發布時'.i18n), type: 'tsunami-silent-v2'), ], ), diff --git a/lib/app/settings/notify/page.dart b/lib/app/settings/notify/page.dart index a039923c0..a65356b9f 100644 --- a/lib/app/settings/notify/page.dart +++ b/lib/app/settings/notify/page.dart @@ -15,6 +15,7 @@ import 'package:dpip/core/providers.dart'; import 'package:dpip/models/settings/location.dart'; import 'package:dpip/models/settings/notify.dart'; import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/utils/log.dart'; import 'package:dpip/widgets/list/list_section.dart'; import 'package:dpip/widgets/list/list_tile.dart'; import 'package:flutter/material.dart'; @@ -84,13 +85,12 @@ class _SettingsNotifyPageState extends State { }) .catchError((error) { if (error.toString().contains('401')) { - if (GlobalProviders.location.latitude != null && GlobalProviders.location.longitude != null) { + if (GlobalProviders.location.coordinates != null) { Future.delayed(const Duration(seconds: 2), () { ExpTech() .updateDeviceLocation( token: Preference.notifyToken, - lat: GlobalProviders.location.latitude.toString(), - lng: GlobalProviders.location.longitude.toString(), + coordinates: GlobalProviders.location.coordinates!, ) .then((_) { if (mounted) { @@ -98,7 +98,7 @@ class _SettingsNotifyPageState extends State { } }) .catchError((updateError) { - print('Failed to update location: $updateError'); + TalkerManager.instance.error('Failed to update location: $updateError'); }); }); } @@ -233,7 +233,7 @@ class _SettingsNotifyPageState extends State { selector: (_, model) => model.evacuation, builder: (context, evacuation, child) { return ListSectionTile( - title: '避難資訊'.i18n, + title: '防災資訊'.i18n, subtitle: Text(getWeatherNotifyTypeName(evacuation)), trailing: const Icon(Symbols.chevron_right_rounded), icon: Symbols.directions_run_rounded, diff --git a/lib/app/welcome/4-permissions/page.dart b/lib/app/welcome/4-permissions/page.dart index 322447162..8491b8212 100644 --- a/lib/app/welcome/4-permissions/page.dart +++ b/lib/app/welcome/4-permissions/page.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:autostarter/autostarter.dart'; import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:dpip/app/home/page.dart'; @@ -56,19 +55,19 @@ class _WelcomePermissionPageState extends State with Widg super.initState(); WidgetsBinding.instance.addObserver(this); _permissionsFuture = _initializePermissions(); - if (Platform.isAndroid) { - _autoStartStatusCheck(); - } + // if (Platform.isAndroid) { + // _autoStartStatusCheck(); + // } WidgetsBinding.instance.addPostFrameCallback((_) async { await _checkNotificationPermission(); setState(() {}); }); } - Future _autoStartStatusCheck() async { - _autoStartStatus = await Autostarter.checkAutoStartState() ?? true; - _autoStartPermission = Future.value(_autoStartStatus); - } + // Future _autoStartStatusCheck() async { + // _autoStartStatus = await Autostarter.checkAutoStartState() ?? true; + // _autoStartPermission = Future.value(_autoStartStatus); + // } Future _checkNotificationPermission() async { if (Platform.isAndroid) { @@ -88,12 +87,12 @@ class _WelcomePermissionPageState extends State with Widg @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { - setState(() async { + setState(() { _permissionsFuture = _initializePermissions(); - if (Platform.isAndroid) { - _autoStartStatus = (await Autostarter.checkAutoStartState())!; - _autoStartPermission = Future.value(_autoStartStatus); - } + // if (Platform.isAndroid) { + // _autoStartStatus = (await Autostarter.checkAutoStartState())!; + // _autoStartPermission = Future.value(_autoStartStatus); + // } }); } } diff --git a/lib/app_old/dpip.dart b/lib/app_old/dpip.dart index 6e1335b89..8d6f589de 100644 --- a/lib/app_old/dpip.dart +++ b/lib/app_old/dpip.dart @@ -6,7 +6,6 @@ import 'package:dpip/app_old/page/me/me.dart'; import 'package:dpip/app_old/page/more/more.dart'; import 'package:dpip/core/fcm.dart'; import 'package:dpip/core/notify.dart'; -import 'package:dpip/core/service.dart'; import 'package:dpip/dialog/welcome/announcement.dart'; import 'package:dpip/dialog/welcome/changelog.dart'; import 'package:dpip/global.dart'; @@ -168,7 +167,6 @@ class _DpipState extends State { void _initializeServices() { fcmInit(); notifyInit(); - initBackgroundService(); } @override diff --git a/lib/app_old/page/map/lightning/lightning.dart b/lib/app_old/page/map/lightning/lightning.dart index a126ff0c6..6bd18a9b9 100644 --- a/lib/app_old/page/map/lightning/lightning.dart +++ b/lib/app_old/page/map/lightning/lightning.dart @@ -49,7 +49,7 @@ class _LightningMapState extends State { Future _loadMap() async { if (Platform.isIOS && (Global.preference.getBool('auto-location') ?? false)) { - await getSavedLocation(); + await updateSavedLocationIOS(); } userLat = Global.preference.getDouble('user-lat') ?? 0.0; diff --git a/lib/app_old/page/map/radar/radar.dart b/lib/app_old/page/map/radar/radar.dart index b78406115..6d7a73db2 100644 --- a/lib/app_old/page/map/radar/radar.dart +++ b/lib/app_old/page/map/radar/radar.dart @@ -1,17 +1,19 @@ import 'dart:io'; +import 'package:flutter/material.dart'; + +import 'package:maplibre_gl/maplibre_gl.dart'; + import 'package:dpip/api/exptech.dart'; +import 'package:dpip/api/route.dart'; import 'package:dpip/core/ios_get_location.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/latlng.dart'; -import 'package:dpip/utils/need_location.dart'; import 'package:dpip/utils/radar_color.dart'; import 'package:dpip/widgets/list/time_selector.dart'; import 'package:dpip/widgets/map/legend.dart'; import 'package:dpip/widgets/map/map.dart'; -import 'package:flutter/material.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; typedef PositionUpdateCallback = void Function(); @@ -47,10 +49,6 @@ class _RadarMapState extends State { bool isUserLocationValid = false; bool _showLegend = false; - String getTileUrl(String timestamp) { - return 'https://api-1.exptech.dev/api/v1/tiles/radar/$timestamp/{z}/{x}/{y}.png'; - } - @override void initState() { super.initState(); @@ -104,7 +102,7 @@ class _RadarMapState extends State { radar_list = await ExpTech().getRadarList(); if (!mounted) return; - final String newTileUrl = getTileUrl(radar_list.last); + final String newTileUrl = Routes.radarTile(radar_list.last); _mapController.addSource('radarSource', RasterSourceProperties(tiles: [newTileUrl], tileSize: 256)); @@ -129,7 +127,7 @@ class _RadarMapState extends State { _mapController.addLayer('radarSource', 'radarLayer', const RasterLayerProperties(), belowLayerId: 'county-outline'); if (Platform.isIOS && GlobalProviders.location.auto) { - await getSavedLocation(); + await updateSavedLocationIOS(); } await _mapController.addSource( @@ -141,36 +139,15 @@ class _RadarMapState extends State { } Future start() async { - userLat = GlobalProviders.location.latitude ?? 0; - userLon = GlobalProviders.location.longitude ?? 0; - - final location = LatLng(userLat, userLon); - - if (location.isValid) { - await _mapController.setGeoJsonSource('markers-geojson', { - 'type': 'FeatureCollection', - 'features': [ - { - 'type': 'Feature', - 'properties': {}, - 'geometry': { - 'coordinates': [userLon, userLat], - 'type': 'Point', - }, - }, - ], - }); - final cameraUpdate = CameraUpdate.newLatLngZoom(LatLng(userLat, userLon), 8); - await _mapController.animateCamera(cameraUpdate, duration: const Duration(milliseconds: 1000)); - } + final location = GlobalProviders.location.coordinates; - if (!mounted) return; - - if (!location.isValid && !GlobalProviders.location.auto) { - await showLocationDialog(context); + if (location != null && location.isValid) { + await _mapController.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); + } else { + await _mapController.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); } - _addUserLocationMarker(); + if (!mounted) return; setState(() {}); } @@ -251,7 +228,7 @@ class _RadarMapState extends State { setState(() {}); }, onTimeSelected: (time) { - final String newTileUrl = getTileUrl(time); + final String newTileUrl = Routes.radarTile(time); _mapController.removeLayer('radarLayer'); _mapController.removeSource('radarSource'); diff --git a/lib/app_old/page/map/tsunami/tsunami.dart b/lib/app_old/page/map/tsunami/tsunami.dart index fc84907fb..732eee1fe 100644 --- a/lib/app_old/page/map/tsunami/tsunami.dart +++ b/lib/app_old/page/map/tsunami/tsunami.dart @@ -55,7 +55,7 @@ class _TsunamiMapState extends State { } if (Platform.isIOS && (Global.preference.getBool('auto-location') ?? false)) { - await getSavedLocation(); + await updateSavedLocationIOS(); } userLat = Global.preference.getDouble('user-lat') ?? 0.0; userLon = Global.preference.getDouble('user-lon') ?? 0.0; @@ -185,7 +185,7 @@ class _TsunamiMapState extends State { textColor: '#ffffff', textHaloColor: '#000000', textHaloWidth: 1, - textFont: ['Noto Sans Regular'], + textFont: ['Noto Sans TC Bold'], textOffset: [ Expressions.literal, [0, 3.5], diff --git a/lib/app_old/page/map/typhoon/typhoon.dart b/lib/app_old/page/map/typhoon/typhoon.dart index 2c4973654..377ebaf67 100644 --- a/lib/app_old/page/map/typhoon/typhoon.dart +++ b/lib/app_old/page/map/typhoon/typhoon.dart @@ -40,7 +40,7 @@ class _TyphoonMapState extends State { typhoonData = await ExpTech().getTyphoonGeojson(); if (Platform.isIOS && (Global.preference.getBool('auto-location') ?? false)) { - await getSavedLocation(); + await updateSavedLocationIOS(); } userLat = Global.preference.getDouble('user-lat') ?? 0.0; userLon = Global.preference.getDouble('user-lon') ?? 0.0; diff --git a/lib/app_old/page/map/weather/humidity.dart b/lib/app_old/page/map/weather/humidity.dart index 049f1347f..4537c2d6c 100644 --- a/lib/app_old/page/map/weather/humidity.dart +++ b/lib/app_old/page/map/weather/humidity.dart @@ -58,7 +58,7 @@ class _HumidityMapState extends State { Future _loadMap() async { if (Platform.isIOS && (Global.preference.getBool('auto-location') ?? false)) { - await getSavedLocation(); + await updateSavedLocationIOS(); } userLat = Global.preference.getDouble('user-lat') ?? 0.0; userLon = Global.preference.getDouble('user-lon') ?? 0.0; @@ -219,7 +219,7 @@ class _HumidityMapState extends State { textColor: '#ffffff', textHaloColor: '#000000', textHaloWidth: 1, - textFont: ['Noto Sans Regular'], + textFont: ['Noto Sans TC Bold'], textOffset: [ Expressions.literal, [0, 2], diff --git a/lib/app_old/page/map/weather/pressure.dart b/lib/app_old/page/map/weather/pressure.dart index f148181a2..26b968535 100644 --- a/lib/app_old/page/map/weather/pressure.dart +++ b/lib/app_old/page/map/weather/pressure.dart @@ -58,7 +58,7 @@ class _PressureMapState extends State { Future _loadMap() async { if (Platform.isIOS && (Global.preference.getBool('auto-location') ?? false)) { - await getSavedLocation(); + await updateSavedLocationIOS(); } userLat = Global.preference.getDouble('user-lat') ?? 0.0; userLon = Global.preference.getDouble('user-lon') ?? 0.0; @@ -221,7 +221,7 @@ class _PressureMapState extends State { textColor: '#ffffff', textHaloColor: '#000000', textHaloWidth: 1, - textFont: ['Noto Sans Regular'], + textFont: ['Noto Sans TC Bold'], textOffset: [ Expressions.literal, [0, 2], diff --git a/lib/core/eew.dart b/lib/core/eew.dart index 5f7e617ba..9b6057631 100644 --- a/lib/core/eew.dart +++ b/lib/core/eew.dart @@ -232,7 +232,7 @@ WaveTime calculateWaveTime(double depth, double distance) { double userLat, double userLon, ) { - final distSurface = LatLng(eqLat, eqLng).to(LatLng(userLat, userLon)); + final distSurface = LatLng(eqLat, eqLng).to(LatLng(userLat, userLon)) /1000; final dist = sqrt(pow(distSurface, 2) + pow(depth, 2)); final pga = 1.657 * exp(1.533 * mag) * pow(dist, -1.607); var intensity = pgaToFloat(pga); diff --git a/lib/core/i18n.dart b/lib/core/i18n.dart index fb8706f65..7afea152f 100644 --- a/lib/core/i18n.dart +++ b/lib/core/i18n.dart @@ -1,7 +1,128 @@ +import 'dart:convert'; + +import 'package:flutter/services.dart'; import 'package:i18n_extension/i18n_extension.dart'; +class I18nCsvLoader { + I18nCsvLoader._(); + + static Future>> fromFile(String path) async { + final csvContent = await rootBundle.loadString(path); + return _parseCsvTranslations(csvContent); + } + + static Map> _parseCsvTranslations(String csvContent) { + final lines = LineSplitter.split(csvContent); + if (lines.isEmpty) return {}; + + // Parse headers + final headers = _parseCsvLine(lines.first); + if (headers.isEmpty || headers[0] != 'key') { + throw const FormatException('CSV must start with "key" column'); + } + + // Extract language codes from headers (skip 'key' column) + final languageCodes = headers.skip(1).toList(); + + // Initialize result map with empty language maps + final Map> result = {}; + for (final langCode in languageCodes) { + result[langCode] = {}; + } + + // Process data rows + for (final line in lines.skip(1)) { + if (line.trim().isEmpty) continue; + + final values = _parseCsvLine(line); + if (values.isEmpty || values[0].isEmpty) continue; + + final key = values[0]; + final translations = values.skip(1).toList(); + + result[key] = {for (final langCode in languageCodes) langCode: translations[languageCodes.indexOf(langCode)]}; + } + + return result; + } + + /// Parse a CSV line, handling quoted fields and commas + static List _parseCsvLine(String line) { + final List result = []; + final StringBuffer current = StringBuffer(); + bool inQuotes = false; + bool lastWasQuote = false; + + for (int i = 0; i < line.length; i++) { + final char = line[i]; + + if (char == '"') { + if (inQuotes && lastWasQuote) { + // Double quote inside quoted field - add single quote + current.write('"'); + lastWasQuote = false; + } else if (inQuotes) { + // End of quoted field + lastWasQuote = true; + } else { + // Start of quoted field + inQuotes = true; + lastWasQuote = false; + } + } else if (char == ',' && (!inQuotes || lastWasQuote)) { + // Field separator + result.add(current.toString()); + current.clear(); + inQuotes = false; + lastWasQuote = false; + } else { + // Regular character + current.write(char); + lastWasQuote = false; + } + } + + // Add final field + result.add(current.toString()); + + return result; + } +} + extension AppLocalizations on String { static final _t = Translations.byFile('zh-Hant', dir: 'assets/translations'); static Future load() => _t.load(); String get i18n => localize(this, _t); } + +extension LocationNameLocalizations on String { + static late final Translations _locationNames; + static bool _isLoaded = false; + + static Future load() async { + if (_isLoaded) return; + + final translations = await I18nCsvLoader.fromFile('assets/translations/location_names.csv'); + + _locationNames = Translations.byId('zh-Hant', translations); + _isLoaded = true; + } + + String get locationName => localize(this, _locationNames); +} + +extension WeatherStationLocalizations on String { + static late final Translations _weatherStations; + static bool _isLoaded = false; + + static Future load() async { + if (_isLoaded) return; + + final translations = await I18nCsvLoader.fromFile('assets/translations/weather_station_names.csv'); + + _weatherStations = Translations.byId('zh-Hant', translations); + _isLoaded = true; + } + + String get weatherStation => localize(this, _weatherStations); +} diff --git a/lib/core/installation_tracker.dart b/lib/core/installation_tracker.dart index 0483126d4..f1c7d0381 100644 --- a/lib/core/installation_tracker.dart +++ b/lib/core/installation_tracker.dart @@ -5,7 +5,6 @@ import 'package:dpip/utils/log.dart'; final talker = TalkerManager.instance; Future initializeInstallationData() async { - talker.log('--- 開始檢查應用程式安裝狀態 ---'); final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final int? installTime = packageInfo.installTime?.millisecondsSinceEpoch; @@ -20,7 +19,6 @@ Future initializeInstallationData() async { final int? storedInstallTime = Preference.installTime; if (storedInstallTime == null || storedVersion == null) { - talker.info('SharedPreferences 中未找到安裝時間或版本記錄。'); talker.info('這是 App 首次安裝。'); Preference.instance.clear(); @@ -49,5 +47,4 @@ Future initializeInstallationData() async { } else { talker.info('應用程式未重新安裝也未升級。使用現有安裝資料。'); } - talker.log('--- 應用程式安裝狀態檢查結束 ---'); } diff --git a/lib/core/ios_get_location.dart b/lib/core/ios_get_location.dart index 10d55146d..da1e78a25 100644 --- a/lib/core/ios_get_location.dart +++ b/lib/core/ios_get_location.dart @@ -1,38 +1,42 @@ import 'dart:async'; +import 'package:flutter/services.dart'; + +import 'package:maplibre_gl/maplibre_gl.dart'; + import 'package:dpip/core/providers.dart'; -import 'package:dpip/utils/location_to_code.dart'; import 'package:dpip/utils/log.dart'; -import 'package:flutter/services.dart'; +import 'package:dpip/utils/map_utils.dart'; const _channel = MethodChannel('com.exptech.dpip/data'); Completer? _completer; -Future getSavedLocation() async { - if (_completer != null && !_completer!.isCompleted) { - return _completer!.future; - } +Future updateSavedLocationIOS() async { + final completer = _completer; + + if (completer != null && !completer.isCompleted) return completer.future; - _completer = Completer(); + _completer = Completer(); try { final result = await _channel.invokeMethod>('getSavedLocation'); - final data = result?.map((key, value) => MapEntry(key, value.toDouble())); - final latitude = data?['lat'] as double?; - final longitude = data?['lon'] as double?; + if (result == null) return; - GlobalProviders.location.setLatLng(latitude: latitude, longitude: longitude); + final latitude = result['lat'] as double?; + final longitude = result['lon'] as double?; if (latitude != null && longitude != null) { - final location = GeoJsonHelper.checkPointInPolygons(latitude, longitude); - print(location); - GlobalProviders.location.setCode(location?.code.toString()); + final code = getTownCodeFromCoordinates(LatLng(latitude, longitude)); + GlobalProviders.location.setCode(code); + GlobalProviders.location.setCoordinates(LatLng(latitude, longitude)); + } else { + GlobalProviders.location.setCode(null); + GlobalProviders.location.setCoordinates(null); } - } catch (e) { - TalkerManager.instance.error('Error in getSavedLocation: $e'); + } catch (e, s) { + TalkerManager.instance.error('Error in getSavedLocation', e, s); } finally { _completer?.complete(); - _completer = null; } } diff --git a/lib/core/location.dart b/lib/core/location.dart deleted file mode 100644 index a1bcf2a4b..000000000 --- a/lib/core/location.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'dart:async'; - -import 'package:dpip/core/providers.dart'; -import 'package:dpip/utils/location_to_code.dart'; -import 'package:dpip/utils/log.dart'; -import 'package:geolocator/geolocator.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; - -StreamSubscription? positionStreamSubscription; -Timer? restartTimer; - -class GetLocationResult { - final bool change; - final int? code; - final double? lat; - final double? lng; - - GetLocationResult({required this.change, this.code, this.lat, this.lng}); - - factory GetLocationResult.fromJson(Map json) { - return GetLocationResult( - change: json['change'] as bool, - code: json['code'] as int?, - lat: json['lat'] as double?, - lng: json['lng'] as double?, - ); - } - - Map toJson() { - return {'code': code, 'change': change, 'lat': lat, 'lng': lng}; - } - - LatLng get latlng => LatLng(lat ?? 0, lng ?? 0); -} - -class LocationService { - static final LocationService _instance = LocationService._internal(); - - factory LocationService() { - return _instance; - } - - LocationService._internal(); - - final GeolocatorPlatform geolocatorPlatform = GeolocatorPlatform.instance; - - @pragma('vm:entry-point') - Future androidGetLocation() async { - final isLocationServiceEnabled = await Geolocator.isLocationServiceEnabled(); - - if (!isLocationServiceEnabled) { - TalkerManager.instance.warning('位置服務未啟用'); - return GetLocationResult(change: false, lat: 0, lng: 0); - } - - bool hasLocationChanged = false; - final lastLatitude = GlobalProviders.location.latitude ?? 0; - final lastLongitude = GlobalProviders.location.longitude ?? 0; - - final currentPosition = await Geolocator.getCurrentPosition( - locationSettings: const LocationSettings(accuracy: LocationAccuracy.medium), - ); - - final currentLocation = GeoJsonHelper.checkPointInPolygons(currentPosition.latitude, currentPosition.longitude); - - final distanceInMeters = Geolocator.distanceBetween( - lastLatitude, - lastLongitude, - currentPosition.latitude, - currentPosition.longitude, - ); - - if (distanceInMeters >= 250) { - GlobalProviders.location.setLatLng(latitude: currentPosition.latitude, longitude: currentPosition.longitude); - GlobalProviders.location.setCode(currentLocation?.code.toString()); - hasLocationChanged = true; - TalkerManager.instance.debug('距離: $distanceInMeters 更新位置'); - } else { - TalkerManager.instance.debug('距離: $distanceInMeters 不更新位置'); - } - - return GetLocationResult( - change: hasLocationChanged, - code: currentLocation?.code, - lat: currentPosition.latitude, - lng: currentPosition.longitude, - ); - } -} diff --git a/lib/core/notify.dart b/lib/core/notify.dart index 876f466b3..fb5b715c8 100644 --- a/lib/core/notify.dart +++ b/lib/core/notify.dart @@ -12,7 +12,7 @@ String? _pendingChannelKey; @pragma('vm:entry-point') Future onActionReceivedMethod(ReceivedAction receivedAction) async { - print(receivedAction); + TalkerManager.instance.debug('Received action: $receivedAction'); final context = router.routerDelegate.navigatorKey.currentContext; if (context == null) { _pendingChannelKey = receivedAction.channelKey; @@ -44,17 +44,27 @@ void _navigateBasedOnChannelKey(BuildContext context, String? channelKey) { context.push(MapPage.route(options: MapPageOptions(initialLayers: {MapLayer.monitor}))); return; } - + if (channelKey.startsWith('int_report')) { context.push(MapPage.route(options: MapPageOptions(initialLayers: {MapLayer.monitor}))); return; } - + if (channelKey.startsWith('eq')) { context.push(MapPage.route(options: MapPageOptions(initialLayers: {MapLayer.monitor}))); return; } - + + if (channelKey.startsWith('report')) { + context.push(MapPage.route(options: MapPageOptions(initialLayers: {MapLayer.report}))); + return; + } + + if (channelKey.startsWith('announcement')) { + context.push('/announcement'); + return; + } + context.go('/home'); } @@ -166,7 +176,7 @@ Future notifyInit() async { defaultColor: Colors.red, ledColor: Colors.red, enableVibration: true, - vibrationPattern: highVibrationPattern, + vibrationPattern: mediumVibrationPattern, ), NotificationChannel( channelGroupKey: 'group_eq', @@ -222,11 +232,27 @@ Future notifyInit() async { ledColor: Colors.red, enableVibration: false, ), + NotificationChannel( + channelGroupKey: 'group_rain', + channelKey: 'thunderstorm-important-v2', + channelName: '山區暴雨(重大)', + channelDescription: '所在地(鄉鎮)發布山區暴雨時', + importance: NotificationImportance.Max, + defaultPrivacy: NotificationPrivacy.Public, + criticalAlerts: true, + playSound: true, + soundSource: 'resource://raw/rain', + defaultColor: Colors.red, + ledColor: Colors.red, + enableVibration: true, + vibrationPattern: highVibrationPattern, + locked: true, + ), NotificationChannel( channelGroupKey: 'group_rain', channelKey: 'thunderstorm-general-v2', channelName: '雷雨即時訊息(一般)', - channelDescription: '所在地(鄉鎮)發布雷雨即時訊息或山區暴雨時', + channelDescription: '所在地(鄉鎮)發布雷雨即時訊息時', importance: NotificationImportance.High, defaultPrivacy: NotificationPrivacy.Public, playSound: true, @@ -270,8 +296,8 @@ Future notifyInit() async { NotificationChannel( channelGroupKey: 'group_evacuation', channelKey: 'evacuation_major-important-v2', - channelName: '避難資訊(重大)', - channelDescription: '所在地(鄉鎮)發布防空、土石流、淹水或堰塞湖避難警訊時', + channelName: '防災資訊(重大)', + channelDescription: '所在地(鄉鎮)發布土石流、淹水或堰塞湖防災警訊時', importance: NotificationImportance.Max, defaultPrivacy: NotificationPrivacy.Public, criticalAlerts: true, @@ -287,8 +313,8 @@ Future notifyInit() async { NotificationChannel( channelGroupKey: 'group_evacuation', channelKey: 'evacuation_minor-general-v2', - channelName: '避難資訊(一般)', - channelDescription: '所在地(鄉鎮)發布防空、土石流、淹水或堰塞湖避難資訊時', + channelName: '防災資訊(一般)', + channelDescription: '所在地(鄉鎮)發布土石流、淹水或堰塞湖防災資訊時', importance: NotificationImportance.High, defaultPrivacy: NotificationPrivacy.Public, playSound: true, @@ -302,7 +328,7 @@ Future notifyInit() async { channelGroupKey: 'group_tsunami', channelKey: 'tsunami-important-v2', channelName: '海嘯資訊(重大)', - channelDescription: '海嘯警報發布時,沿海地區鄉鎮', + channelDescription: '海嘯警報發布時', importance: NotificationImportance.Max, defaultPrivacy: NotificationPrivacy.Public, criticalAlerts: true, @@ -319,7 +345,7 @@ Future notifyInit() async { channelGroupKey: 'group_tsunami', channelKey: 'tsunami-general-v2', channelName: '海嘯資訊(一般)', - channelDescription: '海嘯警報發布時,上述除外地區', + channelDescription: '海嘯消息發布時', importance: NotificationImportance.Default, defaultPrivacy: NotificationPrivacy.Public, playSound: true, @@ -356,6 +382,18 @@ Future notifyInit() async { enableVibration: true, vibrationPattern: lowVibrationPattern, ), + NotificationChannel( + channelKey: 'background', + channelName: '自動定位', + channelDescription: '背景定位服務通知', + importance: NotificationImportance.Low, + defaultColor: const Color(0xFF2196f3), + channelShowBadge: false, + enableVibration: false, + enableLights: false, + playSound: false, + locked: true, + ), ], channelGroups: [ NotificationChannelGroup(channelGroupKey: 'group_eew', channelGroupName: '地震速報音效'), diff --git a/lib/core/preference.dart b/lib/core/preference.dart index 6f7b91fe1..f00f2295a 100644 --- a/lib/core/preference.dart +++ b/lib/core/preference.dart @@ -11,6 +11,7 @@ class PreferenceKeys { static const locationLatitude = 'location:latitude'; static const locationOldLongitude = 'location:oldLongitude'; static const locationOldLatitude = 'location:oldLatitude'; + static const locationFavorited = 'location:favorite'; // #endregion // #region User Interface @@ -45,6 +46,10 @@ class Preference { instance = await SharedPreferencesWithCache.create(cacheOptions: const SharedPreferencesWithCacheOptions()); } + static Future reload() async { + await instance.reloadCache(); + } + static String? get version => instance.getString('app-version'); static set version(String? value) => instance.set('app-version', value); @@ -81,6 +86,9 @@ class Preference { static double? get locationOldLatitude => instance.getDouble(PreferenceKeys.locationOldLatitude); static set locationOldLatitude(double? value) => instance.set(PreferenceKeys.locationOldLatitude, value); + + static List get locationFavorited => instance.getStringList(PreferenceKeys.locationFavorited) ?? []; + static set locationFavorited(List value) => instance.set(PreferenceKeys.locationFavorited, value); // #endregion // #region User Interface diff --git a/lib/core/rts.dart b/lib/core/rts.dart index ee4920035..dc51161d9 100644 --- a/lib/core/rts.dart +++ b/lib/core/rts.dart @@ -1,8 +1,6 @@ -import 'package:dpip/api/model/eew.dart'; -import 'package:dpip/api/model/station_info.dart'; -import 'package:dpip/utils/extensions/latlng.dart'; import 'package:intl/intl.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; + +import 'package:dpip/api/model/station_info.dart'; StationInfo findAppropriateItem(List infos, int date) { final DateTime targetDate = (date == 0) ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(date); @@ -16,25 +14,3 @@ StationInfo findAppropriateItem(List infos, int date) { return sortedItems.last; } - -bool checkBoxSkip(Map eewLastInfo, Map eewDist, List box) { - bool passed = false; - - for (final eew in eewLastInfo.keys) { - int skip = 0; - for (int i = 0; i < 4; i++) { - final dist = LatLng( - eewLastInfo[eew]!.info.latitude, - eewLastInfo[eew]!.info.longitude, - ).to(LatLng(box[i][1], box[i][0])); - - if (eewDist[eew]! > dist) skip++; - } - if (skip >= 4) { - passed = true; - break; - } - } - - return passed; -} diff --git a/lib/core/service.dart b/lib/core/service.dart index 2658230d0..33899d370 100644 --- a/lib/core/service.dart +++ b/lib/core/service.dart @@ -2,250 +2,474 @@ import 'dart:async'; import 'dart:io'; import 'dart:ui'; +import 'package:flutter/services.dart'; + +import 'package:awesome_notifications/awesome_notifications.dart'; +import 'package:flutter_background_service/flutter_background_service.dart'; +import 'package:geojson_vi/geojson_vi.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; + import 'package:dpip/api/exptech.dart'; -import 'package:dpip/app_old/page/map/radar/radar.dart'; -import 'package:dpip/core/location.dart'; +import 'package:dpip/api/model/location/location.dart'; import 'package:dpip/core/preference.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/global.dart'; +import 'package:dpip/utils/extensions/datetime.dart'; import 'package:dpip/utils/extensions/latlng.dart'; -import 'package:dpip/utils/location_to_code.dart'; import 'package:dpip/utils/log.dart'; -import 'package:awesome_notifications/awesome_notifications.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_background_service/flutter_background_service.dart'; -import 'package:intl/intl.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:permission_handler/permission_handler.dart'; -Timer? _locationUpdateTimer; -final _backgroundService = FlutterBackgroundService(); -bool _isAndroidServiceInitialized = false; +class PositionEvent { + final LatLng? coordinates; + final String? code; + + PositionEvent(this.coordinates, this.code); -enum ServiceEvent { setAsForeground, setAsBackground, sendPosition, sendDebug, removePosition, stopService } + factory PositionEvent.fromJson(Map json) { + final coordinates = json['coordinates'] as List?; + final code = json['code'] as String?; -Future initBackgroundService() async { - final isAutoLocationEnabled = GlobalProviders.location.auto; - if (!isAutoLocationEnabled) { - TalkerManager.instance.info('自動定位未啟用,不初始化背景服務'); - return; + return PositionEvent(coordinates != null ? LatLng(coordinates[0] as double, coordinates[1] as double) : null, code); } - final notificationPermission = await Permission.notification.status; - final locationPermission = await Permission.locationAlways.status; + Map toJson() { + return {'coordinates': coordinates?.toJson(), 'code': code}; + } +} - if (notificationPermission.isGranted && locationPermission.isGranted) { - if (!Platform.isAndroid) return; +/// Events emitted by the background service. +final class LocationServiceEvent { + /// Event emitted when a new position is set in the background service. Contains the updated location coordinates. + static const position = 'position'; - await _initializeAndroidForegroundService(); - _setupPositionListener(); - startAndroidBackgroundService(shouldInitialize: true); - } + /// Method event to stop the service. + static const stop = 'stop'; } -Future startAndroidBackgroundService({required bool shouldInitialize}) async { - if (!_isAndroidServiceInitialized) { - await _initializeAndroidForegroundService(); - _setupPositionListener(); +/// Background location service. +/// +/// This class is responsible for managing the background location service. It is used to handle start and stop the +/// service. +class LocationServiceManager { + LocationServiceManager._(); + + /// The notification ID used for the background service notification + static const kNotificationId = 888888; + + /// Instance of the background service + static FlutterBackgroundService? instance; + + /// Platform channel for iOS + static const platform = MethodChannel('com.exptech.dpip/location'); + + /// Whether the background service is available on the current platform + static bool get avaliable => Platform.isAndroid || Platform.isIOS; + + /// Initializes the background location service. + /// + /// Configures the service with Android specific settings. Sets up a listener for position updates that reloads + /// preferences and updates device location. + /// + /// Will starts the service if automatic location updates are enabled. + /// + /// This method is Android specific. + static Future initalize() async { + if (instance != null || !Platform.isAndroid) return; + + TalkerManager.instance.info('👷 initializing location service'); + + final service = FlutterBackgroundService(); + + try { + await service.configure( + androidConfiguration: AndroidConfiguration( + onStart: LocationService._$onStart, + autoStart: false, + isForegroundMode: false, + foregroundServiceTypes: [AndroidForegroundType.location], + notificationChannelId: 'background', + initialNotificationTitle: 'DPIP', + initialNotificationContent: '正在初始化自動定位服務...', + foregroundServiceNotificationId: kNotificationId, + ), + // iOS is handled in native code + iosConfiguration: IosConfiguration(autoStart: false), + ); + + // Reloads the UI isolate's preference cache when a new position is set in the background service. + service.on(LocationServiceEvent.position).listen((data) => _onPosition(PositionEvent.fromJson(data!))); + + instance = service; + TalkerManager.instance.info('👷 service initialized'); + } catch (e, s) { + TalkerManager.instance.error('👷 initializing location service FAILED', e, s); + } + + if (Preference.locationAuto == true) await start(); } - final isServiceRunning = await _backgroundService.isRunning(); - if (!isServiceRunning) { - _backgroundService.startService(); - } else if (!shouldInitialize) { - stopAndroidBackgroundService(); - _backgroundService.startService(); + /// Starts the background location service. + /// + /// Initializes the service if not already initialized. Only starts if the service is not already running. + static Future start() async { + if (!avaliable) return; + + TalkerManager.instance.info('👷 starting location service'); + + try { + if (Platform.isIOS) { + await platform.invokeMethod('toggleLocation', {'isEnabled': true}); + return; + } + + final service = instance; + if (service == null) throw Exception('Not initialized.'); + + if (await service.isRunning()) { + TalkerManager.instance.warning('👷 location service is already running, skipping...'); + return; + } + + await service.startService(); + } catch (e, s) { + TalkerManager.instance.error('👷 starting location service FAILED', e, s); + } } -} -Future stopAndroidBackgroundService() async { - final isServiceRunning = await _backgroundService.isRunning(); - if (!isServiceRunning) return; + /// Stops the background location service by invoking the stop event. + static Future stop() async { + if (!avaliable) return; + + TalkerManager.instance.info('👷 stopping location service'); + + try { + if (Platform.isIOS) { + await platform.invokeMethod('toggleLocation', {'isEnabled': false}); + return; + } + + final service = instance; + if (service == null) throw Exception('Not initialized.'); - final isAutoLocationEnabled = GlobalProviders.location.auto; - if (isAutoLocationEnabled) { - _backgroundService.invoke(ServiceEvent.removePosition.name); + service.invoke(LocationServiceEvent.stop); + } catch (e, s) { + TalkerManager.instance.error('👷 stopping location service FAILED', e, s); + } } - _backgroundService.invoke(ServiceEvent.stopService.name); + /// The event handler for the "position" event. + /// + /// Called when the service has updated the current location. + static Future _onPosition(PositionEvent event) async { + try { + TalkerManager.instance.info('👷 location updated by service, reloading preferences'); + + await Preference.reload(); + GlobalProviders.location.refresh(); + + final fcmToken = Preference.notifyToken; + if (fcmToken.isNotEmpty && event.coordinates != null) { + await ExpTech().updateDeviceLocation(token: fcmToken, coordinates: event.coordinates!); + } + + TalkerManager.instance.info('👷 preferences reloaded'); + } catch (e, s) { + TalkerManager.instance.error('👷 failed to update location', e, s); + } + } } -void _setupPositionListener() { - _backgroundService.on(ServiceEvent.sendPosition.name).listen((event) { - if (event == null) return; +/// The background location service. +/// +/// This service is used to get the current location of the device in the background and notify the main isolate to +/// update the UI with the new location. +/// +/// All property prefixed with `_$` are isolated from the main app. +@pragma('vm:entry-point') +class LocationService { + LocationService._(); - final result = GetLocationResult.fromJson(event); + /// The service instance + static late AndroidServiceInstance _$service; - final latitude = result.lat ?? 0; - final longitude = result.lng ?? 0; + /// The last known location coordinates + static LatLng? _$location; - final location = GeoJsonHelper.checkPointInPolygons(latitude, longitude); + /// Timer for scheduling periodic location updates + static Timer? _$locationUpdateTimer; - GlobalProviders.location.setCode(location?.code.toString()); - GlobalProviders.location.setLatLng(latitude: latitude, longitude: longitude); + /// Cached GeoJSON data for location lookups + static late GeoJSONFeatureCollection _$geoJsonData; - RadarMap.updatePosition(); - }); + /// Cached location data mapping + static late Map _$locationData; - _backgroundService.on(ServiceEvent.sendDebug.name).listen((event) { - if (event == null) return; + /// Entry point for the background service. + /// + /// Sets up notifications, initializes required data, and starts periodic location updates. Updates the notification + /// with current location information. Adjusts update frequency based on movement distance. + @pragma('vm:entry-point') + static Future _$onStart(ServiceInstance service) async { + if (service is! AndroidServiceInstance) return; + _$service = service; - final notificationBody = event['notifyBody']; - TalkerManager.instance.debug('自動定位: $notificationBody'); - }); -} + DartPluginRegistrant.ensureInitialized(); -Future _initializeAndroidForegroundService() async { - if (_isAndroidServiceInitialized) return; - - await AwesomeNotifications().initialize( - null, // 使用預設 launcher icon - [ - NotificationChannel( - channelKey: 'my_foreground', - channelName: '前景自動定位', - channelDescription: '背景定位服務通知', - importance: NotificationImportance.Low, - defaultColor: const Color(0xFF2196f3), - ledColor: Colors.white, - channelShowBadge: false, + await AwesomeNotifications().createNotification( + content: NotificationContent( + id: LocationServiceManager.kNotificationId, + channelKey: 'background', + title: 'DPIP', + body: '自動定位服務啟動中...', locked: true, - playSound: false, - onlyAlertOnce: true, - ) - ], - ); - - await _backgroundService.configure( - androidConfiguration: AndroidConfiguration( - onStart: _onServiceStart, - isForegroundMode: true, - foregroundServiceTypes: [AndroidForegroundType.location], - notificationChannelId: 'my_foreground', - initialNotificationTitle: 'DPIP', - initialNotificationContent: '前景服務啟動中...', - foregroundServiceNotificationId: 888, - ), - iosConfiguration: IosConfiguration(onForeground: _onServiceStart, onBackground: _onIosBackground), - ); - _isAndroidServiceInitialized = true; -} + autoDismissible: false, + icon: 'resource://drawable/ic_stat_name', + badge: 0, + ), + ); -@pragma('vm:entry-point') -Future _onIosBackground(ServiceInstance service) async { - WidgetsFlutterBinding.ensureInitialized(); - DartPluginRegistrant.ensureInitialized(); - return true; -} + await _$service.setAsForegroundService(); -@pragma('vm:entry-point') -Future _onServiceStart(ServiceInstance service) async { - WidgetsFlutterBinding.ensureInitialized(); - DartPluginRegistrant.ensureInitialized(); - if (service is AndroidServiceInstance) { - service.setAsForegroundService(); - await AwesomeNotifications().createNotification( - content: NotificationContent( - id: 888, - channelKey: 'my_foreground', - title: 'DPIP', - body: '前景服務啟動中...', - notificationLayout: NotificationLayout.Default, - locked: true, - autoDismissible: false, - icon: 'resource://drawable/ic_stat_name', - ), - ); -} - await Global.init(); - await Preference.init(); - GlobalProviders.init(); + await Preference.init(); + _$geoJsonData = await Global.loadTownGeojson(); + _$locationData = await Global.loadLocationData(); - final locationService = LocationService(); + _$service.setAutoStartOnBootMode(true); - // Setup service event listeners - service.on(ServiceEvent.stopService.name).listen((event) { - _locationUpdateTimer?.cancel(); - if (service is AndroidServiceInstance) { - service.setAutoStartOnBootMode(false); - } - service.stopSelf(); - TalkerManager.instance.info('背景服務已停止'); - }); - - // Only proceed with Android-specific setup if this is an Android service - if (service is AndroidServiceInstance) { - service.setAutoStartOnBootMode(true); - - // Setup service state change listeners - service.on(ServiceEvent.setAsForeground.name).listen((event) => service.setAsForegroundService()); - service.on(ServiceEvent.setAsBackground.name).listen((event) => service.setAsBackgroundService()); - service.on(ServiceEvent.removePosition.name).listen((event) { - GlobalProviders.location.setCode(null); - GlobalProviders.location.setLatLng(); - }); - - // Define the periodic location update task - Future updateLocation() async { - _locationUpdateTimer?.cancel(); - if (!await service.isForegroundService()) return; + _$service.on(LocationServiceEvent.stop).listen((_) => _$onStop()); + + // Start the periodic location update task + await _$task(); + } + /// The main tick function of the service. + /// + /// This function is used to get the current location of the device and update the notification. It is called + /// periodically to check if the device has moved and update the notification accordingly. + @pragma('vm:entry-point') + static Future _$task() async { + if (!await _$service.isForegroundService()) return; + + final $perf = Stopwatch()..start(); + TalkerManager.instance.debug('⚙️::BackgroundLocationService task started'); + + try { // Get current position and location info - final position = await locationService.androidGetLocation(); - service.invoke(ServiceEvent.sendPosition.name, position.toJson()); + final coordinates = await _$getDeviceGeographicalLocation(); + + if (coordinates == null) { + _$updatePosition(_$service, null); + return; + } - final latitude = position.lat.toString(); - final longitude = position.lng.toString(); - final locationName = - position.code == null - ? '服務區域外' - : '${Global.location[position.code.toString()]?.city}${Global.location[position.code.toString()]?.town}'; + final previousLocation = _$location; - // Handle FCM notification if position changed - final fcmToken = Preference.notifyToken; - if (position.change && fcmToken.isNotEmpty) { - final response = await ExpTech().updateDeviceLocation(token: fcmToken, lat: latitude, lng: longitude); - TalkerManager.instance.debug(response); + final distanceInMeters = previousLocation != null ? coordinates.to(previousLocation) : null; + + if (distanceInMeters == null || distanceInMeters >= 250) { + TalkerManager.instance.debug('⚙️::BackgroundLocationService distance: $distanceInMeters, updating position'); + _$updatePosition(_$service, coordinates); + } else { + TalkerManager.instance.debug( + '⚙️::BackgroundLocationService distance: $distanceInMeters, not updating position', + ); } - // Update notification with current position - const notificationTitle = '自動定位中'; - final timestamp = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()); - final notificationBody = '$timestamp\n$latitude,$longitude $locationName'; - - service.invoke(ServiceEvent.sendDebug.name, {'notifyBody': notificationBody}); - await AwesomeNotifications().createNotification( - content: NotificationContent( - id: 888, - channelKey: 'my_foreground', - title: notificationTitle, - body: notificationBody, - notificationLayout: NotificationLayout.Default, - locked: true, - autoDismissible: false, - ), - ); - service.setForegroundNotificationInfo(title: notificationTitle, content: notificationBody); + // Determine the next update time based on the distance moved + int nextUpdateInterval = 15; + + if (distanceInMeters != null) { + if (distanceInMeters > 30) { + nextUpdateInterval = 5; + } else if (distanceInMeters > 10) { + nextUpdateInterval = 10; + } + } - final double dist = position.latlng.to( - LatLng(GlobalProviders.location.oldLatitude ?? 0, GlobalProviders.location.oldLongitude ?? 0), + _$locationUpdateTimer?.cancel(); + _$locationUpdateTimer = Timer.periodic(Duration(minutes: nextUpdateInterval), (timer) => _$task()); + } catch (e, s) { + $perf.stop(); + TalkerManager.instance.error( + '⚙️::BackgroundLocationService task FAILED after ${$perf.elapsedMilliseconds}ms', + e, + s, ); + } finally { + if ($perf.isRunning) { + $perf.stop(); + TalkerManager.instance.debug('⚙️::BackgroundLocationService task completed in ${$perf.elapsedMilliseconds}ms'); + } + } + } + + /// The event handler for the "stop" event. + /// + /// Called when the service manager sends a stop signal to terminate the location service. + @pragma('vm:entry-point') + static Future _$onStop() async { + try { + TalkerManager.instance.info('⚙️::BackgroundLocationService stopping location service'); + + // Cleanup timer + _$locationUpdateTimer?.cancel(); + + await _$service.setAutoStartOnBootMode(false); + await _$service.stopSelf(); + + TalkerManager.instance.info('⚙️::BackgroundLocationService location service stopped'); + } catch (e, s) { + TalkerManager.instance.error('⚙️::BackgroundLocationService stopping location service FAILED', e, s); + } + } + + /// Gets the current geographical location of the device. + /// + /// Returns null if location services are disabled. Uses medium accuracy for location detection. + @pragma('vm:entry-point') + static Future _$getDeviceGeographicalLocation() async { + final isLocationServiceEnabled = await Geolocator.isLocationServiceEnabled(); + + if (!isLocationServiceEnabled) { + TalkerManager.instance.warning('位置服務未啟用'); + return null; + } + + final currentPosition = await Geolocator.getCurrentPosition( + locationSettings: const LocationSettings(accuracy: LocationAccuracy.medium), + ); + + return LatLng(currentPosition.latitude, currentPosition.longitude); + } + + /// Gets the location code for given coordinates by checking if they fall within polygon boundaries. + /// + /// Takes a target LatLng and checks if it falls within any polygon in the GeoJSON data. Returns the location code if + /// found, null otherwise. + static ({String code, Location location})? _$getLocationFromCoordinates(LatLng target) { + final features = _$geoJsonData.features; + + for (final feature in features) { + if (feature == null) continue; + + final geometry = feature.geometry; + if (geometry == null) continue; + + bool isInPolygon = false; + + if (geometry is GeoJSONPolygon) { + final polygon = geometry.coordinates[0]; + + bool isInside = false; + int j = polygon.length - 1; + for (int i = 0; i < polygon.length; i++) { + final double xi = polygon[i][0]; + final double yi = polygon[i][1]; + final double xj = polygon[j][0]; + final double yj = polygon[j][1]; + + final bool intersect = + ((yi > target.latitude) != (yj > target.latitude)) && + (target.longitude < (xj - xi) * (target.latitude - yi) / (yj - yi) + xi); + if (intersect) isInside = !isInside; + + j = i; + } + isInPolygon = isInside; + } + + if (geometry is GeoJSONMultiPolygon) { + final multiPolygon = geometry.coordinates; + + for (final polygonCoordinates in multiPolygon) { + final polygon = polygonCoordinates[0]; + + bool isInside = false; + int j = polygon.length - 1; + for (int i = 0; i < polygon.length; i++) { + final double xi = polygon[i][0]; + final double yi = polygon[i][1]; + final double xj = polygon[j][0]; + final double yj = polygon[j][1]; + + final bool intersect = + ((yi > target.latitude) != (yj > target.latitude)) && + (target.longitude < (xj - xi) * (target.latitude - yi) / (yj - yi) + xi); + if (intersect) isInside = !isInside; + + j = i; + } + + if (isInside) { + isInPolygon = true; + break; + } + } + } - int time = 15; + if (isInPolygon) { + final code = feature.properties!['CODE']?.toString(); + if (code == null) return null; - if (dist > 30) { - time = 5; - } else if (dist > 10) { - time = 10; + final location = _$locationData[code]; + if (location == null) return null; + + return (code: code, location: location); } + } + + return null; + } + + /// Updates the current position in the service. + /// + /// Invokes a position event with the new coordinates that can be listened to by the main app to update the UI. + @pragma('vm:entry-point') + static Future _$updatePosition(ServiceInstance service, LatLng? position) async { + _$location = position; + + final result = position != null ? _$getLocationFromCoordinates(position) : null; - GlobalProviders.location.setOldLongitude(position.lng); - GlobalProviders.location.setOldLatitude(position.lat); + Preference.locationCode = result?.code; + Preference.locationLatitude = position?.latitude; + Preference.locationLongitude = position?.longitude; - _locationUpdateTimer = Timer.periodic(Duration(minutes: time), (timer) async => updateLocation()); + service.invoke(LocationServiceEvent.position, PositionEvent(position, result?.code).toJson()); + + // Update notification with current position + final timestamp = DateTime.now().toDateTimeString(); + String content = '服務區域外'; + + if (position == null) { + content = '服務區域外'; + } else { + final latitude = position.latitude.toStringAsFixed(6); + final longitude = position.longitude.toStringAsFixed(6); + + if (result == null) { + content = '服務區域外 ($latitude, $longitude)'; + } else { + content = '${result.location.city} ${result.location.town} ($latitude, $longitude)'; + } } - // Start the periodic task - updateLocation(); + const notificationTitle = '自動定位中'; + final notificationBody = + '$timestamp\n' + '$content'; + + await AwesomeNotifications().createNotification( + content: NotificationContent( + id: LocationServiceManager.kNotificationId, + channelKey: 'background', + title: notificationTitle, + body: notificationBody, + locked: true, + autoDismissible: false, + badge: 0, + ), + ); + + _$service.setForegroundNotificationInfo(title: notificationTitle, content: notificationBody); } } diff --git a/lib/core/update.dart b/lib/core/update.dart index 93b73145e..d49a2e353 100644 --- a/lib/core/update.dart +++ b/lib/core/update.dart @@ -1,13 +1,19 @@ import 'dart:async'; import 'dart:math'; -import 'package:dpip/api/exptech.dart'; -import 'package:dpip/core/preference.dart'; import 'package:flutter_icmp_ping/flutter_icmp_ping.dart'; import 'package:ip_country_lookup/ip_country_lookup.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; + +import 'package:dpip/api/exptech.dart'; +import 'package:dpip/core/preference.dart'; Future updateInfoToServer() async { + final latitude = Preference.locationLatitude; + final longitude = Preference.locationLongitude; + try { + if (latitude == null || longitude == null) return; if (Preference.notifyToken != '' && DateTime.now().millisecondsSinceEpoch - (Preference.lastUpdateToServerTime ?? 0) > 86400 * 1 * 1000) { final random = Random(); @@ -15,14 +21,10 @@ Future updateInfoToServer() async { if (rand != 0) return; - ExpTech().updateDeviceLocation( - token: Preference.notifyToken, - lat: Preference.locationLatitude.toString(), - lng: Preference.locationLongitude.toString(), - ); + ExpTech().updateDeviceLocation(token: Preference.notifyToken, coordinates: LatLng(latitude, longitude)); } - unawaited(_performNetworkCheck()); + _performNetworkCheck(); } catch (e) { print('Network info update failed: $e'); } @@ -49,5 +51,3 @@ Future _performNetworkCheck() async { print('Network check failed: $e'); } } - -void unawaited(Future future) {} diff --git a/lib/global.dart b/lib/global.dart index ecd95657f..16076d933 100644 --- a/lib/global.dart +++ b/lib/global.dart @@ -1,33 +1,37 @@ -import 'package:dpip/api/exptech.dart'; -import 'package:dpip/api/model/location/location.dart'; -import 'package:dpip/utils/extensions/asset_bundle.dart'; -import 'package:dpip/utils/location_to_code.dart'; import 'package:flutter/services.dart'; + +import 'package:geojson_vi/geojson_vi.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:dpip/api/exptech.dart'; +import 'package:dpip/api/model/location/location.dart'; +import 'package:dpip/utils/extensions/asset_bundle.dart'; + +typedef TimeTable = Map>; + class Global { Global._(); static late PackageInfo packageInfo; static late SharedPreferences preference; static late Map location; - static late Map geojson; - static late Map> timeTable; - static late Map box; + static late GeoJSONFeatureCollection boxGeojson; + static late GeoJSONFeatureCollection townGeojson; + static late TimeTable timeTable; static late Map notifyTestContent; static ExpTech api = ExpTech(); - static Future loadLocationData() async { + static Future> loadLocationData() async { final data = await rootBundle.loadJson('assets/location.json'); - location = data.map((key, value) => MapEntry(key, Location.fromJson(value as Map))); + return data.map((key, value) => MapEntry(key, Location.fromJson(value as Map))); } - static Future loadTimeTableData() async { + static Future loadTimeTableData() async { final data = await rootBundle.loadJson('assets/time.json'); - timeTable = data.map((key, value) { + return data.map((key, value) { final list = (value as List).map((item) { final map = item as Map; @@ -50,15 +54,35 @@ class Global { }); } + static Future loadBoxGeojson() async { + final data = await rootBundle.loadJson('assets/box.json'); + + return GeoJSONFeatureCollection.fromMap(data); + } + + static Future loadTownGeojson() async { + final data = await rootBundle.loadJson('assets/map/town.json'); + + return GeoJSONFeatureCollection.fromMap(data); + } + static Future init() async { - packageInfo = await PackageInfo.fromPlatform(); - preference = await SharedPreferences.getInstance(); - box = await rootBundle.loadJson('assets/box.json'); + final results = await Future.wait([ + PackageInfo.fromPlatform(), + SharedPreferences.getInstance(), + loadBoxGeojson(), + loadLocationData(), + loadTownGeojson(), + loadTimeTableData(), + ]); - await loadLocationData(); - await loadTimeTableData(); - await loadNotifyTestContent(); + packageInfo = (results[0] as PackageInfo?)!; + preference = (results[1] as SharedPreferences?)!; + boxGeojson = (results[2] as GeoJSONFeatureCollection?)!; + location = (results[3] as Map?)!; + townGeojson = (results[4] as GeoJSONFeatureCollection?)!; + timeTable = (results[5] as TimeTable?)!; - await GeoJsonHelper.loadGeoJson('assets/map/town.json'); + await loadNotifyTestContent(); } } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb deleted file mode 100644 index 7de728b47..000000000 --- a/lib/l10n/app_en.arb +++ /dev/null @@ -1,1801 +0,0 @@ -{ - "@@locale": "en", - "@@context": "App level localization strings.", - "datetime_format": "MM/dd/yyyy HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "EEEE, MM/dd/yyyy", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "MM/dd/yyyy", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "Home", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "Monitor", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "Reports", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "Map", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "Me", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "Settings", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "Adjust how DPIP should function.", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "Donate", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "Follow us on Threads", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "YouTube Livestream", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "Server Status", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "Third Party Libraries", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "M {magnitude} Depth {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "No. {reportNumber}", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "Local Earthquake", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "Web", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "Event Time", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "Location", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "Magnitude", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "Depth", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "Report Image", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "Intensity Map Image", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "Max PGA Image", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "Max PGV Image", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "Intensity in Locations", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "Language", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "Adjust display language of DPIP", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "Display language", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "Translated {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "Approved {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "Help us translate!", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "Click here to help us improve the translation of DPIP", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "Earthquake data is temporarily unavailable", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "No active earthquake warnings", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "Earthquake Early Warning", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "Earthquake Early Warning (Alert)", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "Estimated​", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "Arrive in", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "Unknown", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "Arrived", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "Sec(s)", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "Replay", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "Save", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "Image saved", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "Personalization", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "Theme", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "Adjust appearance and color of DPIP", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "Light", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "Dark", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "Follow system", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "Location", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "Location", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "Adjust your location to receive real-time weather information, estimated earthquake intensity, and estimated arrival time of seismic waves.", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "Enable Automatic Locating", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "The automatic location feature will use the GPS on your device to automatically update your location based on your geographical position, providing real-time weather and earthquake information, so you can stay up-to-date with the latest local conditions.", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "Not set", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "Special Municipalities/County", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "City/Town/District", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "Select Location", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "Copy FCM Token", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "FCM token copied", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "May cause sea level fluctuations.", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "Stay alerted for possible tsunami threats", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "Failed to fetch earthquake report. Check connection and try again.", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "Version {version}\nBuild {buildNumber}\nMade by ExpTech Studio\nPartial Data Source: CWA", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "Source Language", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "Notification Test", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "Test the notification and sound of weather and earthquake alerts", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 4.", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 2.", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "Shaking detected", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "Local (Municipality/County) measured intensity is greater than 3.", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "Earthquake Prediction Warning notification", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "Earthquake Information", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "Other", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "Tsunami Warning (Alert)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "Tsunami Warning Issued\nCoastal Areas", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "Tsunami Warning (Notice)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "Tsunami Warning Issued\nExcluding Above Areas", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "When announcements are published", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "Maps", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "Radar", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "Precipitation", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "Temperature", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "Humidity", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "Pressure", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "Wind/Gust", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "Typhoon", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "Tsunami", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "Legend", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "Unit: dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "Unit: Millimeter (mm)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "Unit: Celsius (°C)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "Unit: Percentage (%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "Unit: hPa", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "History", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "Historical event information within 3 days", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "No historical event information", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "Current event information", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "There is currently no event information", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "No. {serial}", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "Lightning", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "Out of service area", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "Outside the service area, only available in Taiwan", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "Unable to obtain notification permission", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "Try again", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "Unable to obtain location permission", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "Cancel", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "Sunny", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "Overcast", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "More", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "More features", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "General", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "Debug", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech Web", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "Notification History", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "Advanced features", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "Adjust the Advanced Features of DPIP", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "Earthquake Monitor", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "No Tsunami Information", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "Tsunami Warning", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "No. {id}, Update #{serial}", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "release", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "Update", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "Cancelled", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "Estimated tsunami arrival time and wave height", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "Tsunami observed in different areas", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "Time of occurrence", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "Magnitude", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "Depth", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "There are currently no events.", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "Change log", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3 Days", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2 Days", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24 Hours", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12 Hours", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6 Hours", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3 Hours", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1 Hours", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10 Minutes", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "Today", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "Welcome to DPIP", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP is an app designed by a local team in Taiwan. It integrates information from TREM-Net (Taiwan Real-time Earthquake Monitoring Network) and data from the Central Weather Administration, providing a comprehensive, unified, and convenient disaster prevention information application.", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "Next", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "Who are we?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio is a group primarily composed of students, with an average age of under 20 and more than 15 members. The members are students from northern, central, and southern Taiwan, as well as Japan, South Korea, and China.", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "Our Original Intention", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "The original intention was to recruit a group of students interested and skilled in computers and technology. It later expanded beyond the school and gradually developed into its current form.", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "Notice", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP will relay various information from ExpTech and the Central Weather Administration, Taiwan. Please note the following points when using it.", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "All information should be considered authoritative only if it is consistent with what the Central Weather Administration has announced.", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "Due to factors such as network conditions, server performance, application issues, and the status of our data providers, there may be times when you do not receive information. We will do our best to prevent this from happening, but we cannot guarantee uninterrupted service.", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "There's a chance that you will feel strong shaking before you receive the alert.", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "Earthquake Early Warnings are estimates based on quick calculations and could be significantly inaccurate. Users should be aware of this and use the information judiciously.", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "Any action that is not officially approved could lead to legal consequences. It's essential to follow all applicable rules and regulations.", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "Permissions", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "We advocate for the privacy of all users.", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "Notifications", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "When a natural disaster occurs, notifications are used to transmit disaster prevention information.", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "Automatically updates your location settings to provide real-time disaster alerts for your current area.", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "Used for saving visualized data from CWA and ExpTech.", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "Disagree", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "Agree", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "DPIP offers a strong earthquake monitoring service powered by TREM from ExpTech Studio. Please carefully review the following terms and conditions and select whether to enable this service.", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "The real-time earthquake intensity displayed in DPIP is not official and may be different from their measurements. You should rely on the information released by the Central Weather Administration.", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "The Earthquake Monitor is owned wholly by ExpTech Studio, and is not affiliated with the CWA. Please do not forward complaints or suggestions to the CWA, to avoid causing disturbances.", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "The Earthquake Monitor uses TREM (Taiwan Real-time Earthquake Monitoring) to monitor nationwide seismic activity, as a real-time seismic intensity display service. When an earthquake occurs, changes in color of monitor stations can be used to monitor the propagation of seismic waves.", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "The constant background noise from traffic, factories, construction, and other sources can cause the seismograph's color to change even when there's no real shake. Also, since the data is updated live, we can't always tell right away if there's a problem with the seismograph itself, so the color change can also be a hardware malfunction.", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "In June 2022, TREM-Net (TREM Earthquake Observation Network) began to record earthquake data across Taiwan through two observation networks, namely SE-Net (Strong Shock Observation Network Accelerometer) and MS-Net (Weak Shock Observation Network Speedometer).", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "New version available", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "Please update to the latest version for the best experience", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "Current", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "Latest", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "Update Now", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "Skip", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "Update Complete", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIP just Finished Updating, Want to look at the Update Log now?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "Remind me later", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "Take me there", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "Announcements", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "Do you want to check out the New Announcement?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "No Announcements", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "Contributors", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "Unable to load the Change Log, Please Retry Later.", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "No update logs", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "Announcement Details", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "Version Details", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "Unable to get Permission", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "An error occurred while saving the image", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "Confirm", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "No search results", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "Always Allow", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "Always", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "For better experience with DPIP, please give the \"Auto Start\" Permission to let us set your Local Information.", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "For better experience when using DPIP, you need to Enable the Permission for \"Auto Start\" to make sure DPIP is getting the info normally.", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "Auto Start Permission", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "For a better experience, please give permission for location access to allow for DPIP to automatically set background location information.", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "For better experience when using DPIP, you need to Enable the Permission for \"Auto Start\" to make sure DPIP is getting the info Normally.", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "Disable Power Saving", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "You have notification permissions declined. Please go to your device settings and enable notifications for this app.", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "Autostart permission had been denied, please go to System Settings to allow it.", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "Power Saving Policy has been denied, please move to Setting Allowed Permissions.", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "Permission request", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "Users need to manually go to settings to enable relevant permissions.", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "Location not set", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP needs your Location to work. Click \"Go to Settings\" to set up your location and try again.", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "Go to Settings", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "App Log", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "An error occurred while copying FCM Token", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "Estimated intensity legend", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "Only for earthquake emergency reporting", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5-", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5+", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6-", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6+", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "Lightning to ground within 5 minutes", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "Lightning to ground within 10 minutes", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "Lightning to ground within 30 minutes", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "Lightning to ground within 60 minutes", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "Lightning in the clouds in 5 minutes", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "Lightning in the clouds in 10 minutes", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "Lightning in the clouds in 30 minutes", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "Lightning in the clouds in 60 minutes", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "Abnormal", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "Network connection or server abnormality.", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "Retry", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "Please go to the application settings to find and allow the \"Photos and Media\" permission and try again.", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "There is currently no notification history", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "Emergency", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "Notification details", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "Notification sending area", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "Emergency notifications", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "General Notifications", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "Please enable notifications for DPIP in your system settings and try again.", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "Please go to the application settings to find and allow the \"Location\" permission and try again.", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "No data available", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "This page presents an overview of the server status during each period. The raw data is updated every 5 seconds, and a condensed version is shown here to optimize network usage. Please note that this information is for reference only, and the actual situation should be subject to the announcement.", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "All normal", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "All exceptions", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "Partial exception", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "Normal", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "Unstable", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "No data", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "Foreground Auto-locating", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "{lat_abs}º S", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "{lat}º N", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "{lon_abs}º W", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "{lon}º E", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "Delay: {serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "What the devs want to say", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "About", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "Alerted Area", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "Estimated", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "Time of Occurrence", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "Unable to access Earthquake Monitor", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "Please enable the Earthquake Monitor in Advanced Features in Settings.", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "Click to view information", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "Highest", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "Lowest", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": " (Disabled)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "Introduction", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "Firstly, I'd like to thank all the users, and to everyone in the development team, I'd like to express my most sincere gratitude.", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP is an application that aims to be a center for disaster prevention-related information, and we hope it can become an invaluable asset to everyone's daily lives. Although the application's development is not complete, we continue to work towards this goal.", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "In developing this application, we invested a lot of money, time and effort, with over $500,000NTD spent on staff costs, equipment costs, cloud services, network fees and other expenditures. Thus, we wish to be able to have the support of our users, by continuing to maintain operations without the use of third-party companies.", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "Monetization Model", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "To sustain the development of our app, our team has had numerous in-depth discussions about how to monetize it. We've explored various options, searching for a suitable monetization model. We found that most similar software adopts in-app advertisements. This led us to initially consider this approach as our primary monetization method.", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "Monetization is Tough", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "We conducted a survey to gauge the public's willingness to pay for such an app. We discovered that most people generally lack a strong sense of disaster preparedness and are unlikely to spend money on it. Our backend data supports this finding. Statistics show that only about one in 100,000 users actively contribute financially. This made in-app advertisements seem like the most viable solution.", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "Why do we not have advertisements?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "During a disaster, the last thing people want to see is an ad. This is the primary reason we've decided against in-app advertisements. For a disaster prevention app, delivering accurate and timely information is paramount. If ads hinder users from accessing critical disaster information, it would directly contradict our mission. Additionally, communication quality is often poor during disasters, and wasting precious data on ad loading is simply frustrating.", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "Charging Users?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "If in-app advertisements aren't feasible, what about charging users? Should we turn it into a paid app?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "First of all, as a disaster prevention app, our goal is to reach as many people as possible. Moreover, those who truly need this app may not have the extra funds to pay for it. We want to help as many people as possible. Secondly, as developers, we want our app to have a wide user base. Charging users would directly reduce the user base.", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "How Do We Monetize?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "In conclusion, we hope to cultivate a community of individuals who are interested in disaster prevention and value this kind of app. We invite these users to support our development efforts and join us in making a difference.", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP Founder's Message", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "Announcement Retrieval Error", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "Slow down!", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "It seems like you're going a bit too fast. Please take a moment and try again later.", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "OK", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "Error: Unable to retrieve FCM Token", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "There's an error occurred while retrieving notification history.\nPlease try again later.", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "For optimal auto-location service performance, DPIP requires enabling notification permissions.", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "For optimal auto-location service performance, DPIP requires enabling location service permissions.", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "Location Permissions", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "For a better automatic locating experience, please grant DPIP the \"{permissionType}\" on Location permission so it can continuously update your location in the background.", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "Auto-locating requires granting {permissionType} to operate in the background.", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "Error:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "Precipitation", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "Nationwide", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "Welcome screen", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "Help us maintain server stability and development.", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "Max Intensity", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "All", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "Filter", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "Reset", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "Apply", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "End of list", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "Event Time", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "Valid until", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "Affected Area", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "Emergency Earthquake Early Warning (Critical)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "Emergency Earthquake Early Warning", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "Emergency Earthquake Early Warning (Silent)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "Maximum intensity is greater than 5- and local (City/Town/District) estimated intensity is greater than 1.", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "Earthquake Early Warning (Critical)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "Local (City/Town/District) estimated intensity is greater than 4.", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "Earthquake Early Warning", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "Local (City/Town/District) estimated intensity is greater than 2.", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "Earthquake Early Warning (Silent)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "Local (City/Town/District) estimated intensity is greater than 1.", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "Intensity Report", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "Local (City/Town/District) measured intensity is greater than 3.", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "Intensity Report (Silent)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "Local (City/Town/District) measured intensity is greater than 1.", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "Earthquake Monitor", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "Earthquake Report", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "Earthquake Report (Silent)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "Local (Municipality/County) measured intensity is greater than 1.", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "Weather Warning", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "Heavy Rain Advisory", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "Weather Advisory", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "Local (City/Town/District) Thunderstorm Advisory or Mountain Area Heavy Rain Advisory Issued", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "Local (City/Town/District) Red Severe Weather Advisory Issued", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "Local (City/Town/District) Severe Weather Advisory Issued Excluding Above Areas", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "Disaster Information", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "Evacuation Advisory", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "When a critical evacuation notice is issued for the current location (City/Town/District)", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "When a minor evacuation notice is issued for the current location (City/Town/District)", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "Tsunami Report (Silent)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "According to the tsunami warning issued by the PTWC, which is\nassessed by CWA that it may cause public concern.", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "Other Notifications", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "Critical", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "Sunny With Haze", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "Sunny With Mist", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "Sunny with lightning", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "Sunny with fog", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "Sunny drizzle", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "Sunny with sleet", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "Sunny with heavy snow", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "Sunny with snowdrops", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "Sunny with ice pellets", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "Sunny with snow showers", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴陣雨雪", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "Sunny with hail", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "Sunny with thunderstorm", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴有雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴有雷雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "Sunny with severe thunderstorm", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "Sunny with thundery and hail", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "Sunny with thunder", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "Cloudy", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "Cloudy with haze", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "Cloudy with mist", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "Cloudy with lighting", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "Cloudy with fog", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "Cloudy with rain", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "Cloudy with sleet", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "Cloudy with heavy snow", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "Cloudy with snowdrops", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "Cloudy with ice beads", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "Cloudy with snow showers", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "Cloudy with rain and snow showers", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "Cloudy with hail", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "Cloudy with thunderstorm", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "Cloudy with thunder and snow", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "Cloudy with thunder and hail", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "Cloudy with thunderstorm", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "Cloudy with heavy thunder and hail", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "Cloudy with thunder", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "Overcast with haze", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "Overcast with mist", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "Overcast with lighting", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "Overcast with fog", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "Overcast with rain", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "Overcast with rain and snow", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "Overcast with heavy snow", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "Overcast with snow beads", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "陰有冰珠", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "陰有陣雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "陰陣雨雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "陰有雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "陰有雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "陰有雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "陰有雷雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "陰大雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "陰大雷雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "Cloudy with thunder.", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "Error in retrieving weather data", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "Average", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "Radar synthetic echo", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "Dismissed", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "Active", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "To save images, DPIP requires \"Photos and Media\" permissions.", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "Error in saving images.", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "An error has occurred.", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(Final Report)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "Set location", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM Observation Network Measured Intensity", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "JMASIS Standard (0.3-sec 3D accel)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "The data presented is automatically generated by TREM-Net and has not undergone human review or verification. It is intended for preliminary emergency response reference only. Please refer to CWA for official information.", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "No available data to display.", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH:00", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "Leaderboard", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "Data time: {time}\n{ranked_length} weather stations", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "According to", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "Descending", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "Ascending", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "Scope", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "Save", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24 Hour {type} Trend", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "Disable Power Saving", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "Allow DPIP to run continuously in the background for instant disaster notification information.", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "Automatic start-up", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "Allow DPIP to run continuously in the background for instant disaster notification information.", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - } -} \ No newline at end of file diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb deleted file mode 100644 index 8bdd1623d..000000000 --- a/lib/l10n/app_ja.arb +++ /dev/null @@ -1,1801 +0,0 @@ -{ - "@@locale": "ja", - "@@context": "App level localization strings.", - "datetime_format": "yyyy/MM/dd HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "yyyy/MM/dd", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "ホーム", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "強震モニタ", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "地震情報", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "地図", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "アプリ情報", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "設定", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "DPIPの動作を調整", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "寄付する", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "Threadsでフォロー", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "YouTubeライブ配信", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "サーバーステータス", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "サードパーティライブラリ", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "M {magnitude} 深さ {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "ID #{reportNumber} の顕著な地震", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "局地地震", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "地震情報", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "発生時刻", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "震源地", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "マグニチュード", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "深さ", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "地震情報図", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "震度分布図", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "地動最大加速度", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "地動最大速度", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "各地の震度", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "言語", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "DPIPの言語を変更する", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "表示言語", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "翻訳済み {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "校正済み {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "翻訳を協力", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "DPIPの翻訳を改善する", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "最新の緊急地震速報が取得できません", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "緊急地震速報が発表されていません", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "地震速報", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "緊急地震速報", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "現在地の予想", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "到達まで", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "不明", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "到達", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "秒", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "リプレイ", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "保存", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "保存しました", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "個人用", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "テーマ", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "DPIPの外観と色を変更する", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "ライト", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "ダーク", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "システムのテーマに従う", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "位置", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "現在地", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "現在地を変更して、リアルタイムの天気情報や地震情報を取得する", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "自動で位置情報を取得する", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "この機能はデバイスのGPSを使用して、地理的な位置情報に基づいて所在地を更新します。リアルタイムの天気情報や地震情報を提供し、最新の地域状況を取得します。", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "未設定", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "都道府県", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "市町村", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "現在地を選択", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "FCMトークンをコピー", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "FCMトークンをコピーしました", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "この地震により若干の海面変動があります", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "この地震により津波発生のおそれがあります。今後の情報にご注意ください。", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "地震情報取得中にエラーが発生しました。ネットワークの状態をご確認の上、再度お試しください。", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "バージョン {version}\nビルド番号 {buildNumber}\n製作:ExpTech Studio\n一部の情報源:CWA(中央気象署)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "元言語", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "通知テスト", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "リアルタイム雨雲レーダーと緊急地震速報で効果音テスト", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "予想最大震度が5弱以上かつ\n現在地(町村)の予想震度が4以上", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "予想最大震度が5弱以上かつ\n現在地(町村)の予想震度が2以上", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "揺れを検出", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "現在地(都道府県)の実測震度が3以上", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "緊急地震速報の効果音", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "地震情報", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "その他", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "津波警報(警報)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "沿岸地域(町村)に居るときに\n津波警報が発表された場合", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "津波警報(注意)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "沿岸地域以外に居るときに\n津波警報が発表された場合", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "お知らせが送信された場合", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "地図リスト", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "レーダー", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "降水量", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "気温", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "湿度", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "気圧", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "風向・風速", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "台風", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "津波情報", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "凡例", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "単位:dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "単位:ミリメートル (mm)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "単位:セルシウス度 (℃)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "単位:相対湿度(%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "単位:ヘクトパスカル (hPa)", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "履歴", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "3日以内の履歴のイベント情報", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "履歴の無いイベント情報", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "現在の地震イベント", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "現在イベント情報はありません", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "第 {serial} 報", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "落雷", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "サービスエリア外", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "台湾以外ではご利用いただけません", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "データが取得できません", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "再試行", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "位置情報が取得できません", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "キャンセル", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "晴れ", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "曇り", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "詳細", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "その他の機能リスト", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "一般", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "デバッグ", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech 公式", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "通知履歴", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "高度な機能", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "DPIPの高度な機能の調整", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "リアルタイム震度モニタ(台湾)の有効化", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "最近の津波情報なし", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "津波警報", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "ID #{id} 第{serial}報", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "發布", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "更新", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "解除", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "津波の到達予想時刻と波高", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "各地で観測された津波", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "発生日時", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "マグニチュード", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "深さ", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "何も起こらず順調です。", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "更新履歴", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3日間", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2日間", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24時間", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12時間", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6時間", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3時間", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1時間", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10分間", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "今日", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "DPIPへようこそ", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "防災情報プラットフォーム", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIPは台湾の現地チームによって設計されたアプリです。TREM-Net(台湾リアルタイム地震観測網)の情報と台湾中央氣象署(CWA)のデータを統合し、便利な防災情報アプリを提供します。", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "次へ", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "私たちは誰?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studioは、15人以上の学生で構成される、平均年齢20歳以下のグループです。台湾(北部、中部、南部)、日本、韓国、中国出身のメンバーで構成されます。", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "私たちの初心", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "コンピューターやテクノロジーに興味と能力のある学生を集めるために学校内で設立されましたが、その後校外に発展し、徐々に現在の形になりました。", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "注意事項", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIPでは、ExpTechや台湾中央氣象署(CWA)からの様々な情報をお届けします。ご利用の際には以下の点にご留意ください。", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "いかなる情報も、台湾中央氣象署(CWA)が発表した内容に基づいています。", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "ネットワークの状態、サーバーの状態、アプリケーションの状態、上流のデータソースの状態などにより、情報が届かない可能性があります。そのような事態が発生しないよう最善を尽くしますが、保証はいたしかねます。", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "通知よりも先に強い揺れが到達する可能性があります。", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "地震情報は速報的な計算の結果であり、大きな誤差が生じる可能性があるため、注意深く理解して利用する必要があります。", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "公的に認可されていない行為は、中華民国(台湾)の法律により、リスクを伴う可能性がありますので、必ず関連法規を遵守してください。", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "権限", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "私たちは常にユーザーの側に立ち、プライバシーの保護に継続的に取り組んでいます。", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "通知", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "大規模災害発生時に通知を通じてリアルタイムの防災情報を伝達します", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "位置情報を使用して現在地設定を自動更新し、現地のリアルタイム防災情報を提供します", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "台湾中央氣象署またはExpTechが提供する画像を保存する", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "同意しない", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "同意する", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "DPIPアプリ上では、ExpTech社のTREMによる強震監視サービスをご利用いただけます。サービスをご利用になるには、以下の契約条項をよくお読みになり、同意していただく必要があります。", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "表示されるリアルタイムの震度は、中央気象署(CMA)が提供する情報ではなく、最終的には中央気象署が発表する情報に従うべき観測結果とは一致しない可能性があります。", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "強震モニタで使用している観測点はExpTechが所有しており、中央気象署(CWA)の管理下ではありません。中央気象署に故障やコメントを送信することは迷惑となりますので、行わないでください。", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "強震モニターはTREM(台湾リアルタイム地震モニタ)を用いて、台湾全体の振動を観測します。リアルタイムの地震度表示機能として、地震が発生した際には、観測点の色の変化を通じて地震波の伝播状況を観察することができます。", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "正常な状態でも、日常的なノイズ(車、工場、工事など)により観測点の色が変化することがあります。また、観測点の故障によっても色が変わることがあります。データはリアルタイムで提供されるため、その場で故障の有無を判断することはできません。", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "2022年6月上旬に、台湾全土で観測点の配備を開始しました。TREM-Net(TREM地震観測網)は、SE-Net(強震観測網「加速度計」)とMS-Net(微震観測網「速度計」)の2つの観測網から構成され、地震時の様々なデータをまとめて記録します。", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "新しいバージョンが見つかりました", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "最新バージョンにアップデートして、最高の体験をお楽しみください", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "現在のバージョン", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "新しいバージョン", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "今すぐ更新", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "スキップ", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "更新完了", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIPが更新されました、変更履歴をご覧になりますか?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "後で", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "表示する", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "お知らせ", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "新しいお知らせを確認しますか?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "現在、お知らせがありません", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "貢献者", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "変更履歴を読み込めませんでした。", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "変更履歴はありません。", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "お知らせの詳細", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "バージョン情報", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "権限がありません", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "画像の保存中にエラーが発生しました", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "確認", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "検索結果なし", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "常に許可", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "永遠に", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "より良いオートロケーションを体験するには、「自動起動許可」を指定し、DPIPがバックグラウンドで自動的に現在地を設定するように、オートアクティベーションの許可を与える必要があります。", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "DPIPをより良く使用するには、バックグラウンドでの実行を許可し、いつでもDPIPからの通知を適切に受信できるようにしてください。", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "自動起動許可", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "より良いオートロケーションを体験するためには、「制限のない」を指定し、DPIPがバックグラウンドで自動的に現在地を設定することを許可する必要があります。", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "DPIPをより良く使用するには、「制限のない」を指定し、バックグラウンドでDPIPからの通知を適切に受信できるようにしてください。", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "低電力モード", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "通知機能が拒否されている場合は、設定ページに移動し、通知許可を設定してください。", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "自動起動の権限がありません。", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "省電力ポリシーが拒否されました。", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "権限管理請求", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "ユーザーは手動で設定ページに移動、関連する権限を有効にする必要があります。", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "現在地が設定されていません", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIPを正しく動作させるには、現在地を設定する必要があります。「設定ページに移動」をタップして、現在地を設定し、再度お試しください。", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "設定ページに移動", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "アプリログ", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "FCMトークンのコピー中にエラーが発生しました", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "予想震度の凡例", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "緊急地震速報が発表された場合のみ", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5弱", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5強", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6弱", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6強", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "5分間以内の対地放電(落雷)", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "10分間以内の対地放電(落雷)", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "30分間以内の対地放電(落雷)", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "1時間以内の対地放電(落雷)", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "5分間以内の雲放電", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "10分間以内の雲放電", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "30分間以内の雲放電", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "1時間以内の雲放電", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "異常", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "ネットワーク接続またはサーバーの異常。", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "再試行", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "アプリケーションの設定で 「写真と動画」の権限を探して許可したうえで、もう一度試してください。", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "通知記録なし", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "緊急", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "通知の詳細情報", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "通知の送信地域", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "緊急通知", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "一般通知", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "アプリケーションの設定で 「通知」の許可を探して許可し、もう一度試してください。", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "アプリケーションの設定で 「位置」の許可を探して許可し、もう一度試してください。", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "情報なし", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "このページでは、様々な時間におけるサーバーの状態の概要を示します。生データは5秒ごとに更新されますが、ここではネットワーク利用を最適化するために凝縮したものを表示しています。この情報はあくまで参考情報であり、実際のステータスはアナウンスに基づいてください。", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "全て正常", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "全て異常", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "部分的な異常", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "正常", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "不安定", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "データ無し", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "前景オートロケーション", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "南緯{lat_abs}度", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "北緯 {lat} 度", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "西経 {lon_abs} 度", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "東経 {lon} 度", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "遅延: {serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "開発者からのメッセージ", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "情報", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "警報地域", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "予想最大震度", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "発生", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "リアルタイム震度モニタが無効です", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "設定の「高度な機能」で、リアルタイム震度モニタを有効にしてください。", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "Tipsはこちら", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "最高", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "最低", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": "(未使用)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "紹介", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "まずはじめに、このソフトウェアをダウンロードしてくださったすべてのユーザーの皆様に、開発チーム一同、心より感謝申し上げます。", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIPは、あらゆる防災情報を統合して発信し、人々の生活に溶け込むことを目指したソフトウェアです。このソフトウェアはまだまだ未完成であり、開発に当たっては困難もありますが、目標に向かって努力を続けていく所存です。", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "当ソフトウェアの開発には、人件費、設備費、クラウドサービス・ネットワーク費用など、合計50万ニュー台湾ドル以上の費用に加え、膨大な時間、労力を費やしてきました。そのためにも、ユーザーの皆様のご支持をいただき、他社に依存することなく運営を継続していきたいと考えております。", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "収益モデル", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "アプリの開発を続けるため、私たちのチームは、採算をとる方法について何度も激論を交わしました。多くの選択肢の中から適切な収益モデルを模索しました。その結果、同種のソフトの多くが広告によって採算をとっていることがわかり、一時はこの方式を採算方式として採用することも検討しました。", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "利益を上げる困難", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "人々の意識を調査したところ、一般的に防災に対する意識は低く、防災のためにお金を使う可能性はさらに低いことがわかりました。バックエンドのデータがこの主張を裏付けています。統計的に、熱心なスポンサーの数はユーザー全体の10万人に1人程度であり、ますます、広告を埋め込むことが最良の解決策であるように思えました。", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "なぜ広告を使わないのか?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "災害が起きた時、広告を見たい人は絶対にいません。これが広告を出さない第一の理由です。防災に特化したソフトは、防災情報を早く正確に届けることが第一です。広告によって正しい防災情報が得られなくなるとしたら、それは私たちの理念に反します。さらに、通信品質が低下することが多い災害時に、広告を読み込むために通信量を浪費するのは悔しいことです。", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "一般の人々に課金するのはどうだろう?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "広告を挿入してもうまくいかないなら、一般の人々に課金するのはどうだろう?有料ソフトにする?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "まず、防災情報ソフトとして、できるだけ多くの人に防災情報を届けたい。また、余計な出費ができない人も含め、できるだけ多くの人を助けたい。そして、開発者としては、できるだけ多くの人に使ってもらいたい。\n一方で、有料化は利用意欲の低下に直結し、これらの目標に反します。", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "どうすれば利益を上げられるのか?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "まとめると、防災に興味を持ち、大切にしてくれる人を育て、ソフト開発をサポートし、ともに前進していきたいという考えです。", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIPの開発者が言いたいこと", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "お知らせ取得中にエラーが発生しました:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "無効な操作", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "操作間隔が短すぎるため、後で再試行してください。", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "OK", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "エラー:FCMトークンを取得できません", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "通知記録取得中にエラーが発生しました", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "自動的に現在地を設定する機能を使用するには、DPIPに通知権限を許可する必要があります。", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "自動的に現在地を設定する機能を使用するには、DPIPに位置情報の取得を許可する必要があります。", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "ロケーション許可", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "より良いオートロケーションを体験するには、「{permissionType}」を指定し、DPIPがバックグラウンドで自動的に現在地を設定するように、オートアクティベーションの許可を与える必要があります。", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "自動的に現在地を設定する機能を使用するには、「{permissionType}」を指定し、許可を付与する必要があります。", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "エラー:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "降水量", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "全国(台湾)", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "ようこそ", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "安定したサーバーの維持と長期的な発展にご協力ください", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "最大震度", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "すべて", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "フィルター", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "初期化", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "適用する", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "一番下にスクロール", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "発表時刻", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "有効期限", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "被害地域", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "緊急地震速報(重大な通知)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "緊急地震速報(一般な通知)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "緊急地震速報(サイレント通知)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "予想最大震度が5弱以上かつ\n現在地(町村)の予想震度が1以上", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "緊急地震速報 (重大な通知)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "現在地(町村)の予想震度が4以上", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "緊急地震速報 (一般な通知)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "現在地(町村)の予想震度が2以上", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "緊急地震速報 (サイレント通知)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "現在地(町村)の予想震度が1以上", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "震度速報(一般な通知)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "現在地(町村)の実測震度が3以上", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "震度速報(サイレント通知)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "現在地(町村)の実測震度が1以上", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "地震モニタ(一般な通知)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "地震情報(一般な通知)", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "地震情報(サイレント通知)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "現在地(都道府県)の実測震度が1以上", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "気象警報", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "リアルタイムの雷雨情報", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "天気警報・特報", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "現在地(町村)にリアルタイム雷雨情報や山間部の暴雨が発表された場合", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "現在地(町村)に赤信号の気象警報が発令された場合", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "現在地(町村)に上記以外の気象警報は発令されている", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "防災情報", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "避難情報", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "現在地(町村)に避難勧告が発表された場合", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "現在地(町村)に避難情報が発表された場合", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "PTWC津波情報 (通知音なし)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "PTWCによって津波情報が発表された場合", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "その他の通知", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "重大な通知", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "晴れと煙霧", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "晴れと靄", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "晴れと落雷", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "晴れと霧", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "晴れと雨", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "晴れと霙", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "晴れと大雪", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "晴れと雪の玉", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "晴れと氷の玉", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "晴れ時々雪", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴れ時々みぞれ", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "晴れと雹", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "晴れと雷雨", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴れと雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴れと雷と雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "晴れと大きな雷雨", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "晴れと大きな雷と雹", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "晴れと雷", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "雲の多い", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "雲の多いと煙霧", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "雲の多いと靄", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "雲の多いと落雷", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "雲の多いと霧", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "雲の多いと雨", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "雲の多いと霙", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "雲の多いと大雪", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "雲の多いと雪の玉", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "曇り時々みぞれ", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "曇り時々雪", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "曇り時々雨か雪", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "雲の多いと雹", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "雲の多いと雷雨", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "雲の多いと雷雪", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "雲の多いと雷と雹", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "雲の多いと大きな雷雨", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "雲の多いと大きな雷と雹", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "曇り時々雷雨", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "曇り空と煙霧", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "曇り空と靄", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "曇り空と落雷", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "曇り空と霧", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "曇り空と雨", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "曇り空と霙", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "曇り空と大雪", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "曇り空と雪の玉", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "曇り空と氷の玉", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "曇り時々雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "曇り時々雨か雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "曇り空と雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "曇り空と雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "曇り空と雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "曇り空と雷と雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "曇り空と大きな雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "曇り空と大きな雷と雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "曇り空と雷", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "天気の取得に失敗しました", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "平均", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "合成レーダー", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "終了済", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "有効中", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "写真を保存するには、DPIPが正しく機能するために、写真とメディアの使用許可を許可する必要があります。", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "画像の保存中にエラーが発生しました:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "エラーが発生した:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(最終報)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1級", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2級", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3級", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4級", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7級", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "タップして現在地を設定する", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 観測点における実測震度", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "日本気象庁(JMA)震度階級(0.3秒3成分合成加速度)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "この情報はTREM-Netの自動観測結果から得られたものであり、目視による検証は行っていません。実際の結果は、台湾中央氣象署(CWA)から発表される情報を参照してください。", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "表示する有効なデータがない", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH時間", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "ランキング", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "資料時間:{time}\n合計 {ranked_length} 観測点", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "並び順", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "降順", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "昇順", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "統合する", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "保存", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24時間{type}のトレンド", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "低電力モード", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "DPIPをバックグラウンドで実行し、災害情報通知を即座に入手できるようにする。", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "自動起動", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "デバイスの再起動やシャットダウン後でもDPIPが自動的に起動し、継続的に防災通知情報を入手することができるようにする。", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - } -} \ No newline at end of file diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb deleted file mode 100644 index a796933b5..000000000 --- a/lib/l10n/app_ko.arb +++ /dev/null @@ -1,1801 +0,0 @@ -{ - "@@locale": "ko", - "@@context": "App level localization strings.", - "datetime_format": "yyyy/MM/dd HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "yyyy/MM/dd", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "홈", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "강진 모니터", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "지진 보고", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "지도", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "사용자", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "설정", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "DPIP의 동작을 조정합니다.", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "저희에게 후원해주세요.", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "Threads 팔로우", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "Youtube 생방송", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "서버 상태", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "서드파티 라이브러리 라이선스", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "규모 {magnitude} 깊이 {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "ID {reportNumber} 의 현저한 유감 지진", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "소구역 유감 지진", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "보고서 페이지", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "발생 시각", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "위치", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "지진의 규모", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "진원 깊이", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "지진 보고", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "진도", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "최대 지반 가속도", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "최대 지반 속도", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "각지의 진도", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "언어", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "DPIP의 표시 언어 조정", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "표시 언어", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "번역 완료 {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "검토 완료 {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "번역 돕기", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "여기를 눌러 DPIP 번역 개선을 도와주세요", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "일시적으로 지진 속보를 받을 수 없습니다", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "현재 발생 중인 지진 속보가 없습니다", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "지진 속보", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "긴급 지진 속보", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "예상 진도", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "지진파", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "알 수 없음", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "도달", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "초 후 도달", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "다시보기", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "이미지 저장", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "이미지 저장 완료", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "개인 설정", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "테마 색", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "DPIP 전체의 외관과 색상을 조정합니다", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "밝은", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "어두운", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "시스템 테마 따르기", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "위치", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "현재 위치", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "현재 위치를 조정하여 실시간 날씨 정보, 지진 예상 진도 및 지진파 도착 예상 시간을 수신하세요", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "자동 위치 지정 사용", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "자동 위치 지정 기능은 장치의 GPS를 사용하여 지리적 위치를 기반으로 위치를 자동으로 업데이트하고, 실시간 날씨 및 지진 정보를 제공하여 항상 최신 현지 상황을 파악할 수 있도록 합니다.", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "설정되지 않음", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "현·시", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "향·진", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "위치 선택", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "FCM Token 복사", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "FCM Token이 복사되었습니다", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "지진으로 해수면 변동 가능성 있음.", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "지진으로 쓰나미 가능성, 정보 주의.", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "지진 보고서를 가져오는 중 오류가 발생했습니다. 네트워크 상태를 확인한 후 다시 시도해 주세요.", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "버전 {version}\n빌드 번호 {buildNumber}\n제작 Exptech 디스커버리 테크놀로지\n부분 출처 CWA (중앙 기상청)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "출처 언어", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "알림 테스트", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "실시간 날씨 정보, 지진 속보 등의 음성 알림을 테스트하다", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "최대진도 5약 이상과\n소재지(향ㆍ진) 예상 진도 4 이상", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "최대진도 5약 이상과\n소재지(향ㆍ진) 예상 진도 2 이상", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "흔들림이 감지되었습니다", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "소재지(향ㆍ진) 실측 진도 2 이상", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "지진 속보 효과음", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "지진정보", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "기타", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "쓰나미 경보 (경보)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "쓰나미 경보 발령시\n해역 부근의 향ㆍ진", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "쓰나미 경보 (주의)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "쓰나미 경보 발령 시\n이하 제외 지역", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "공지사항 전송 시", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "지도 목록", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "레이더", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "강우", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "기온", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "습도", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "기압", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "풍향/풍속", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "태풍", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "쓰나미 정보", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "범례", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "단위: dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "단위: 밀리미터 (mm)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "단위: 섭씨 (°C)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "단위: 상대 습도 (%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "단위: 헥토파스칼 (hPa)", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "이력", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "3일간의 이벤트 정보", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "과거 이벤트 정보 없음", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "현재 이벤트 정보", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "현재 이벤트 정보 없음", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "제 {serial} 보", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "번개", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "서비스 불가 지역", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "서비스 불가 지역, 대만 국내에서만 이용 가능합니다.", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "알림 권한을 얻을 수 없습니다.", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "다시 시도해 주세요.", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "위치 권한을 얻을 수 없습니다.", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "취소", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "맑음", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "흐림", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "더보기", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "더 많은 기능", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "일반", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "디버그", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech 공식 웹사이트", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "푸시 알림 기록", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "고급 기능", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "DPIP 의 고급 기능 조정", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "강진 모니터링 활성화", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "최근에 쓰나미 정보가 없습니다.", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "쓰나미 경보", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "ID{id} 제{serial}보", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "발표됨", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "갱신", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "해제", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "예상 쓰나미 도착 시간 및 파고", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "각지에서 관측된 쓰나미", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "발생 시각", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "규모", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "깊이", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "모든 것이 평안합니다.", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "업데이트 로그", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3일", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2일", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24시간", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12시간", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6시간", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3시간", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1시간", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10분", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "오늘", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "DPIP에 오신 것을 환영합니다", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "방재정보 플랫폼", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP는 TREM-Net(대만의 실시간 지진 관측 네트워크) 정보 및 중앙 기상청 자료를 통합하여 통합, 단일 및 편리한 방재 정보 응용 프로그램을 제공하는 대만 현지 팀이 설계한 앱입니다.", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "다음 단계", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "저희에 관하여", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio는 대부분 학생으로 구성된 팀으로, 평균 연령이 20세 이하이며, 15명 이상의 인원이 참여하고 있습니다. 멤버들은 대만 북부, 중부, 남부, 일본, 한국, 중국의 학생들로 구성되어 있습니다.", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "우리의 목표", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "설립 초기의 목적은 컴퓨터와 기술에 관심과 능력이 있는 학생들을 모집하는 것이었으며, 이후에는 학교 밖으로 발전하여 현재의 모습으로 발전하였습니다.", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "주의사항", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP는 ExpTech 및 대만 기상청으로부터 다양한 정보를 전달하므로, 다음 사항의 유의하여 사용하십시오.", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "모든 정보는 대만 기상청에서 발표한 내용을 기준으로 합니다.", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "네트워크 상태, 서버 상태, 애플리케이션 상태, 상위 데이터 소스 상태 등 여러 요인에 따라 정보를 수신되지 않을 가능성이 있으며, 이를 방지하기 위해 최선을 다하겠지만 발생하지 않을 것이라고 보장하지는 않습니다.", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "강한 진동이 알림보다 사용자 위치에 먼저 도착할 가능성이 있습니다.", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "지진 속보는 빠른 계산 결과로, 상당한 오차가 있을 수 있으니 이해하고 신중히 사용해 주세요.", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "공식적으로 인정되지 않은 모든 행위는 법적 위험을 부담할 수 있으므로 관련 규범을 준수해야 합니다.", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "권한", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "우리는 항상 사용자와 함께하며 사용자의 프라이버시를 위해 끊임없이 노력합니다.", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "알림", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "중대 재해 발생 시 알림으로 즉각 방재 정보를 전달합니다.", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "GPS를 이용하여 소재지 위치를 자동으로 업데이트하고, 현지의 즉각적인 방재 정보를 제공합니다.", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "대만 기상청 또는 ExpTech에서 제공하는 데이터 시각화 이미지를 저장하는 데 사용", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "동의하지 않음", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "동의", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "DPIP 에서 ExpTech의 TREM 강진 모니터링 서비스를 확인할 수 있습니다. 아래 조건을 자세히 읽고 활성화 여부를 선택하세요.", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "표시된 실시간 진도는 대만 기상청에서 제공한 자료가 아니므로 대만 기상청에서 관측한 결과와 일치하지 않을 수 있으며, 대만 기상청에서 발표한 정보를 기준으로 삼아야 합니다.", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "지진 모니터에서 사용하는 지진계는 ExpTech 소유이며, 대만 기상청의 관리하에 있지 않습니다. 대만 기상청에 고장이나 의견을 전달하지 말아 주세요. 이로 인해 기상청에 불편을 초래할 수 있습니다.", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "지진 모니터는 TREM(대만 즉시 지진 모니터링)에서 대만 전역의 현재 진동을 관측하여 실시간 진도 표시 기능을 제공합니다. 지진 발생 시에는 스테이션의 색상 변화를 통해 지진파 전파 상황을 관찰할 수 있습니다.", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "일상적인 잡음(자동차, 공장, 건설 등) 때문에 평소에도 스테이션의 색상이 변할 수 있습니다. 또한, 실시간 데이터이기 때문에 현재로서는 고장 여부를 판단할 수 없으므로, 지진계 고장으로 인해 색상이 변할 수도 있습니다.", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "2022년 6월 초부터 대만 전역에 지진계를 배치하기 시작했습니다. TREM-Net(TREM 지진관측망)은 SE-Net(강진 관측망 '가속도계')과 MS-Net(미세 진동 관측망 '속도계')의 두 개의 관측 네트워크로 구성되어 있으며, 지진 발생 시 다양한 데이터를 기록합니다.", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "새 버전 발견", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "최상의 경험을 위해 최신 버전으로 업데이트하기", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "현재 버전", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "최신 버전", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "지금 업데이트", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "지금은 건너뛰기", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "업데이트 완료", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIP가 업데이트가 완료되었습니다. 업데이트 로그를 보러 가시겠습니까?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "나중에 보기", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "보기로 이동", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "공지", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "새로운 공지가 있습니다. 확인하러 가시겠습니까?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "현재 공지가 없습니다.", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "기여자", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "업데이트 로그를 불러올 수 없습니다. 나중에 다시 시도해 주세요.", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "현재 업데이트 로그가 없습니다.", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "구체적인 공지 사항", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "버전 세부정보", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "권한을 얻을 수 없습니다.", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "이미지를 저장하는 동안 오류가 발생했습니다.", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "확인", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "검색결과가 없습니다", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "모두 허용", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "항상", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "더 나은 자동 위치 추적 경험을 위해, DPIP가 백그라운드에서 자동으로 위치 정보를 설정할 수 있도록 '자동 실행 권한'을 부여해야 합니다.", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "더 나은 DPIP 경험을 위해, DPIP가 백그라운드에서 정상적으로 경고 알림을 수신할 수 있도록 '자동 실행 권한'을 부여해야 합니다.", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "자동 실행 권한", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "더 나은 자동 위치 추적 경험을 위해, DPIP가 백그라운드에서 자동으로 위치 정보를 설정할 수 있도록 '위치' 권한을 항상 허용해야 합니다.", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "더 나은 DPIP 경험을 위해, DPIP가 백그라운드에서 정상적으로 경고 알림을 수신할 수 있도록 '제한 없음' 권한을 부여해야 합니다.", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "전원 절약 설정", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "알림 기능이 거부되었습니다. 설정으로 이동하여 권한을 허용해 주세요.", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "自啟動權限已被拒絕,請移至設定允許權限。", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "省電策略已被拒絕,請移至設定允許權限。", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "권한 요청", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "사용자가 수동으로 설정에서 관련 권한을 활성화해야 합니다.", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "위치가 설정되지 않았습니다.", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP는 위치 설정이 필요합니다. '설정으로 이동'을 클릭하여 위치를 설정한 후 다시 시도해 주세요.", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "설정으로 이동", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "앱 로그", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "FCM 토큰 복사 중 오류 발생", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "예상 진도 범례", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "지진 속보 시에만 사용", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5약", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5강", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6약", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6강", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "5분 이내 지상 번개", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "10분 이내 지상 번개", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "30분 이내 지상 번개", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "60분 이내 지상 번개", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "5분 이내 구름 사이 번개", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "10분 이내 구름 사이 번개", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "30분 이내 구름 사이 번개", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "60분 이내 구름 사이 번개", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "이상", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "네트워크 연결 또는 서버 이상", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "다시 시도", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "애플리케이션 설정에서 '사진 및 미디어' 권한을 찾아 허용한 후 다시 시도해 주세요.", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "알림 기록 없음", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "긴급", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "알림 세부 정보", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "알림 발송 지역", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "긴급 알림", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "일반 알림", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "애플리케이션 설정에서 '알림' 권한을 찾아 허용한 후 다시 시도해 주세요.", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "애플리케이션 설정에서 '위치' 권한을 찾아 허용한 후 다시 시도해 주세요.", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "사용할 수 있는 데이터가 없습니다.", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "이 페이지는 서버의 시간대별 상태 개요를 보여줍니다. 원본 데이터는 5초마다 업데이트되며, 여기서는 네트워크 사용량을 최적화하기 위해 축약된 버전을 표시합니다. 참고로, 이 정보는 참고용일 뿐 실제 상황은 공지를 기준으로 합니다.", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "모두 정상", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "모두 이상", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "일부 이상", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "정상", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "불안정", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "데이터 없음", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "자동 범위 설정", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "남위 {lat_abs} 도", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "북위 {lat} 도", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "서경 {lon_abs} 도", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "동경 {lon} 도", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "지연: {serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "개발자가 하고 싶은 말", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "정보", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "경보 구역", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "예상 최대진도", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "발생 시각", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "강진모니터 표시 안함", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "설정의 기능 단계로 가서 강진모니터를 켜주세요.", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "클릭해서 알림 보기", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "최고", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "최저", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": " (미사용)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "소개", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "이 앱을 다운로드해 주신 모든 사용자분들께 개발팀 전체가 진심으로 감사드립니다.", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP는 모든 방재 정보를 통합하는 것을 목표로 하는 앱으로서 국민 생활에 필수적인 부분이 되고 싶습니다. 아직은 완성도가 떨어지고 어려움이 많지만 우리는 목표를 향해 계속 나아갈 것입니다.", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "소프트웨어를 개발할 때 우리는 많은 돈과 시간, 에너지를 투자했으며 인건비, 장비 비용, 클라우드 서비스, 네트워크 비용 및 기타 항목에 50만 대만 달러 이상을 투자했습니다. 이를 위해 다른 제3자 회서에 의존하지 않고 계속 운영할 수 있도록 사용자의 지지를 받고 싶습니다.", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "영리 모델", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "앱 개발을 유지하기 위해 팀 내에서 어떻게 하면 수익을 낼 수 있는지에 대한 치열한 토론이 여러 번 이루어졌습니다. 우리는 많은 방안 중에서 적합한 수익 모델을 찾으려고 노력합니다. 우리는 대부분의 동일한 유형의 소프트웨어가 영리 목적을 달성하기 위해 간접 광고를 사용한다는 것을 발견하여 한때 이 방법을 영리 방안으로 고려했습니다.", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "영리화의 어려움", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "사용자의 유로화 의향을 조사한 결과, 대부분의 사용자는 일반적으로 방재에 대한 인식이 부족하고 이 문제에 돈을 투자하지 않는 것으로 나타났습니다. 백그라운드의 데이터는 이를 방증하는데, 열성 후원자는 전체 이용자의 약 10만 분의 1에 달하는 것으로 집계되어 PPL이 가장 좋은 해결책으로 보여집니다.", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "왜 광고가 아닌가요?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "재해가 발생했을 때 광고를 보고 싶어하지 않겠죠? 이것이 우리가 PPL을 하지 않는 첫 번째 이유입니다. 방재 지향 소프트웨어는 방재 정보를 빠르고 정확하게 전달하는 것이 최우선 과제입니다. 광고 때문에 방재 정보를 제대로 파악하지 못한다면 오히려 우리의 이념과 어긋납니다. 게다가 재해 시에는 통상적으로 통신 품질이 좋지 않고, 인터넷 트래픽을 추가로 낭비해 광고를 싣고 있으니 답답할 노릇입니다.", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "대중들에게는 유료인가요?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "PPL이 안된다면 일반 대중들을 위한 요금은 어떻게 되나요? 유료 앱이 되나요?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "우선 방재앱으로서 최대한 많은 사람들에게 방재정보를 전달하면 좋을 것 같습니다. 그리고 정말 필요한 사람들은 더 이상 추가 비용을 부담할 수 없을지도 모릅니다. 우리는 더 많은 사람들을 돕고 싶습니다. 둘째, 개발자인 우리는 소프트웨어를 많은 사람들이 사용할 수 있기를 바라며, 요금은 곧 여러분의 사용 의향 저하로 이어질 것입니다.", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "어떻게 이윤을 남기나요?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "위와 같이 방재에 관심 있는 사람, 방재를 중시하는 사람을 육성하여 우리의 소프트웨어 개발을 지원하고 함께 발전해 나가고 싶습니다.", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP 개발자의 말씀", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "공지사항을 가져오던 중 오류가 발생했습니다:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "유효하지 않은 레슨입니다", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "작동 간격이 너무 짧습니다. 잠시 후 다시 시도하십시오.", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "알겠습니다", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "오류: FCM 토큰을 가져올 수 없음", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "알림 기록을 불러오던 중 오류 발생", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "자동 위치추적 기능은 DPIP가 알림 권한을 사용할 수 있도록 허용해야 재대로 작동합니다.", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "자동 위치추적 기능은 DPIP가 위치 권한을 사용할 수 있도록 허용해야 재대로 작동합니다.", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "위치 권한", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "보다 나은 자동 위치추적 경험을 제공하기 위해서 DPIP가 백드라운드에서 위치를 자동으로 설정하도록 위치 권한을 \"{permissionType}\"으로 올려야 합니다.", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "자동 위치추적 기능은 위치 권한을 \"{permissionType}\"로 올려서 백그라운드에서 사용돼야 합니다.", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "오류:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "강수량", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "전국", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "환영 페이지", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "서버의 안정과 장기적인 발전 돕기", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "최대진도", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "전부", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "필터", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "리셋", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "적용", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "마지막", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "전달 시각", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "유효 시각", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "영향 영역", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "긴급지진속보(거대)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "긴급지진속보(일반)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "긴급지진속보(무음)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "최대진도 5약 이상,\n소재지(향ㆍ진) 예상 진도 1 이상", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "지진속보(거대)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "소재지(향ㆍ진) 예상 진도 4 이상", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "지진속보(일반)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "소재지(향ㆍ진) 예상 진도 2 이상", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "지진속보(무음)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "소재지(향ㆍ진) 예상 진도 1 이상", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "진도속보(일반)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "소재지(향ㆍ진) 실측 진도 3 이상", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "진도속보(무음)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "소재지(향ㆍ진) 실측 진도 1 이상", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "강진모니터(일반)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "지진보고(일반)", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "지진보고(무음)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "소재지(현ㆍ시) 실측 진도 1 이상", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "기상경보", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "뇌우 재난 문자", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "기상 경보", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "소재지(현ㆍ시)으로 뇌우 실시간 정보 또는 산간지역 호우 시 전송합니다.", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "소재지(향진)에서 적색 기상 경보 특보를 발령", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "소재지(향진)에서 기상 경보를 발령", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "재난 정보", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "피난 정보", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "소재지(향진)에 피난 경보가 발령된 경우", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "소재지(향진)에 피난정보가 발령된 경우", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "태평양 쓰나미 소식(무음)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "태평향 쓰나미 소식 발표 시", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "기타 정보", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "거대", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "맑고 연무", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "맑고 이슬비", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "맑고 번개", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "맑고 안개", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "맑고 비", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "맑고 진눈깨비", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "맑고 폭설", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "맑고 싸락눈", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "맑고 작은 우박", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "맑고 눈보라", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "맑고 진눈깨비 소나기", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "맑고 우박", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "맑고 뇌우", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "맑고 천둥을 동반한 눈", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "맑고 천둥번개", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "맑고 강한 뇌우", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "맑고 강한 천둥번개", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "맑고 천둥", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "부분적으로 흐림", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "연무를 동반한 부분적으로 흐림", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "이슬비를 동반한 부분적으로 흐림", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "천둥을 동반한 부분적으로 흐림", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "안개를 동반한 부분적으로 흐림", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "비를 동반한 부분적으로 흐림", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "진눈깨비를 동반한 부분적으로 흐림", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "폭설을 동반한 부분적으로 흐림", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "싸락눈을 동반한 부분적으로 흐림", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "작은 우박을 동반한 부분적으로 흐림", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "눈보라를 동반한 부분적으로 흐림", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "진눈깨비 소나기를 동반한 부분적으로 흐림", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "우박을 동반한 부분적으로 흐림", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "뇌우를 동반한 부분적으로 흐림", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "눈과 번개를 동반한 부분적으로 흐림", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "천둥번개를 동반한 부분적으로 흐림", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "강한 뇌우를 동반한 부분적으로 흐림", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "강한 천둥번개를 동반한 부분적으로 흐림", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "천둥을 동반한 부분적으로 흐림", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "연무로 뒤덮인", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "이슬비로 뒤덮인", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "번개로 뒤덮인", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "안개로 뒤덮인", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "비로 뒤덮인", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "진눈깨비로 뒤덮인", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "폭설로 뒤덮인", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "싸락눈으로 뒤덮인", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "작은 우박으로 뒤덮인", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "눈보라로 뒤덮인", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "진눈깨비 소나기로 뒤덮인", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "우박으로 뒤덮인", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "뇌우로 뒤덮인", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "눈보라로 뒤덮인", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "천둥번개로 뒤덮인", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "맑고 강한 천둥번개", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "흐리고 강한 천둥번개", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "흐리고 천둥", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "날씨 이상징후 확인", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "평균", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "기상 레이더", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "종료", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "시행 중", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "사진을 저장하려면 DPIP에 사진 및 미디어 사용 권한을 허용해야 정상적으로 작동합니다.", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "사진 저장 후 오류가 발생했습니다:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "오류 발생:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(마지막)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1급", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2급", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3급", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4급", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7급", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "클릭해서 위치 설정하기", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 관측망 실측 진도", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "JMA 진도 기준 (0.3초 주기의 3성분 합성가속도)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "본 자료는 TREM-Net 관측망 자동관측 결과로부터 얻은 것으로 아직 인위적으로 검토 및 확인되지 않았으며, 참고 자료로만 제공되었습니다. 실제로는 중앙 기상청에서 발표한 정보가 우선입니다.", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "표시할 유효한 자료가 없습니다.", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH시", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "랭킹", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "자료 시간: {time}\n총 {ranked_length} 관측점", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "에 따르면", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "내림차순", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "오름차순", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "통합", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "이미지 저장", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24小時{type}趨勢", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "전원 절약 설정", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "自動化啟動", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - } -} \ No newline at end of file diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb deleted file mode 100644 index 4c65aa4b5..000000000 --- a/lib/l10n/app_ru.arb +++ /dev/null @@ -1,1801 +0,0 @@ -{ - "@@locale": "ru", - "@@context": "App level localization strings.", - "datetime_format": "yyyy/MM/dd HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "yyyy/MM/dd", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "Главная", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "монитор сильного землетрясения", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "отчёт о землетрясении", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "Карта", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "мне", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "Настройки", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "調整 DPIP 的運作方式。", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "пожертвовать нас", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "在 Threads 上追蹤我們", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "YouTube прямая трансляция", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "состояние сервера", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "第三方套件授權", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "M {magnitude} 深度 {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "編號 {reportNumber} 顯著有感地震", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "小區域有感地震", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "страница сообщения о землетрясении", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "發震時間", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "位於", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "величина", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "глубина", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "地震報告圖", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "震度圖", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "最大地動加速度圖", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "最大地動速度圖", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "各地震度", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "язык", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "調整 DPIP 的顯示語言", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "языка дисплея", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "已翻譯 {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "已校對 {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "協助翻譯", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "點擊這裡來幫助我們改進 DPIP 的翻譯", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "暫時無法取得地震速報資料", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "目前無生效中的地震速報", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "地震速報", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "緊急地震速報", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "интенсивность оценки вашего местоположения", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "сейсмические волны", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "неизвестно", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "прибытие", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "秒後抵達", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "воспроизведение", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "сохранение", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "сохранённое", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "персонализация", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "主題色", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "調整 DPIP 整體的外觀與顏色", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "Светлая тема", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "Тёмный тема", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "системной тема", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "местоположение", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "ваше местоположение", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "調整所在地來接收即時天氣資訊、地震預估震度以及地震波預估抵達秒數等", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "включить авто определение местоположения", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "自動定位功能將使用您的裝置上的 GPS ,根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "Не настроено", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "город", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "посёлок", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "выберите местоположение", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "копия FCM Token", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "копия FCM Token успех", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "此地震可能引起若干海面變動", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "此地震可能引起海嘯 注意後續資訊", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "取得地震報告時發生錯誤,請檢查網路狀況後再試一次。", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "版本 {version}\n組建 {buildNumber}\n由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "來源語言", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "通知測試", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "測試即時天氣資訊、地震速報等音效通知", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 4 以上", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "偵測到晃動", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "所在地(縣市)實測震度 3 以上", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "地震速報音效", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "地震資訊", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "другие", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "海嘯警報(警報)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "海嘯警報發布時\n沿海地區鄉鎮", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "海嘯警報(注意)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "海嘯警報發布時\n上述除外地區", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "發送公告時", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "地圖列表", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "雷達回波", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "降水", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "температура", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "влажность", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "воздух давление", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "направление ветра/скорость ветра", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "тайфун", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "информация о цунами", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "圖例", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "Единица измерения: dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "Единица измерения: миллиметр (мм)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "Единица измерения: градус Цельсия (°C)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "Единица измерения: относительная влажность (%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "Единица измерения: гектопаскаль (гПа)", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "история", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "3天內的歷史事件資訊", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "沒有歷史事件資訊", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "目前的事件資訊", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "目前沒有事件資訊", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "Отчет № {serial}", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "閃電", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "服務區域外", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "服務區域外,僅在臺灣各地可用", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "無法取得通知權限", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "再試一次", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "無法取得位置權限", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "取消", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "晴", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "陰", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "更多", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "更多功能列表", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "一般", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "отладка", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech 官網", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "行動通知推播紀錄", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "進階功能", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "調整 DPIP 的進階功能", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "啟用強震監視器", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "近期無海嘯資訊", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "海嘯警報", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "{id}號 第{serial}報", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "發布", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "更新", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "解除", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "預估海嘯到達時間及波高", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "各地觀測到的海嘯", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "發生時間", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "規模", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "深度", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "一切平安,無事件發生。", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "更新日誌", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3 天", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2 天", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24 小時", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12 小時", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6 小時", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3 小時", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1 小時", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10 分鐘", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "今日", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "歡迎使用 DPIP", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "防災資訊平台", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "下一步", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "我們是誰?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "我們的初衷", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "注意事項", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "任何資訊應以中央氣象署發布之內容為準。", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "強烈搖晃有機率比通知早抵達使用者所在地。", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "權限", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "我們一直和使用者站在一起,為使用者的隱私而不斷努力。", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "通知", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "在重大災害發生時以通知來傳遞即時防災資訊", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "使用定位來自動更新所在地設定,提供當地的即時防災資訊", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "不同意", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "同意", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "發現新版本", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "更新至最新版本以獲得最佳體驗", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "目前版本", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "最新版本", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "立即更新", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "暫時略過", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "更新完成", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIP 更新完成,要前往查看更新日誌嗎?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "稍後再說", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "前往查看", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "公告", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "有新的公告,要前往查看嗎?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "目前沒有公告", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "貢獻者", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "無法載入更新日誌,請稍後再試。", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "目前沒有更新日誌", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "公告詳情", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "版本詳情", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "無法取得權限", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "儲存圖片時發生錯誤", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "確定", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "無搜尋結果", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "一律允許", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "永遠", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "自啟動權限", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "省電策略", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "通知功能已被拒絕,請移至設定允許權限。", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "自啟動權限已被拒絕,請移至設定允許權限。", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "省電策略已被拒絕,請移至設定允許權限。", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "權限請求", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "需要使用者手動到設定開啟相關權限。", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "尚未設定所在地", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP 需要設定所在地才能正常運作。點擊「前往設定」設定所在地後再試一次。", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "前往設定", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "App 日誌", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "複製 FCM Token 時發生錯誤", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "預估震度圖例", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "僅用於地震速報時", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5弱", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5強", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6弱", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6強", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "5 分鐘內對地閃電", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "10 分鐘內對地閃電", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "30 分鐘內對地閃電", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "60 分鐘內對地閃電", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "5 分鐘內雲間閃電", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "10 分鐘內雲間閃電", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "30 分鐘內雲間閃電", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "60 分鐘內雲間閃電", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "異常", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "網路連線或伺服器異常。", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "重試", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "沒有通知紀錄", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "緊急", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "通知詳細資訊", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "通知發送區域", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "緊急通知", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "一般通知", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "請您到應用程式設定中找到並允許「通知」權限後再試一次。", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "請您到應用程式設定中找到並允許「位置」權限後再試一次。", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "沒有可用的資料", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "全部正常", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "全部異常", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "部分異常", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "正常", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "不穩定", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "無資料", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "前景自動定位", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "南緯 {lat_abs} 度", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "北緯 {lat} 度", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "西經 {lon_abs} 度", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "東經 {lon} 度", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "延遲: {serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "開發者想說的話", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "關於", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "警報區域", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "預估最大震度", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "發震", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "未啟用強震監視器", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "請至設定進階功能中開啟強震監視器。", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "點擊查看提示資訊", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "最高", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "最低", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": " (未啟用)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "簡介", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "營利模式", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "營利真的太難了", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "為什麼不採用廣告?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "對大眾收費?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "如果植入廣告行不通,那對大眾收費呢?變成付費軟體?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "如何營利?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP 開發者的話", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "獲取公告時發生錯誤:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "無效操作", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "操作間隔過短,請稍後再嘗試。", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "知道了", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "錯誤: 無法取得 FCM Token", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "獲取通知紀錄時發生錯誤", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "位置權限", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "錯誤:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "降水量", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "全國", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "歡迎頁面", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "幫助我們維護伺服器的穩定和長久發展", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "最大震度", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "全部", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "篩選器", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "重置", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "套用", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "到底了", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "發送時間", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "有效至", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "影響區域", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "緊急地震速報(重大)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "緊急地震速報(一般)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "緊急地震速報(無聲)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "地震速報(重大)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "所在地(鄉鎮)預估震度 4 以上", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "地震速報(一般)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "所在地(鄉鎮)預估震度 2 以上", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "地震速報(無聲)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "所在地(鄉鎮)預估震度 1 以上", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "震度速報(一般)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "所在地(鄉鎮)實測震度 3 以上", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "震度速報(無聲通知)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "所在地(鄉鎮)實測震度 1 以上", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "強震監視器(一般)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "地震報告(一般)", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "地震報告(無聲通知)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "所在地(縣市)實測震度 1 以上", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "氣象警報", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "雷雨即時訊息", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "天氣警特報", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "所在地(鄉鎮)發布雷雨即時訊息或\n山區暴雨時", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "所在地(鄉鎮)發布紅色燈號之\n天氣警特報", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "所在地(鄉鎮)發布上述除外燈號之\n天氣警特報", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "災害資訊", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "避難資訊", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "所在地(鄉鎮)發布避難警訊時", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "所在地(鄉鎮)發布避難資訊時", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "太平洋海嘯消息(無聲通知)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "太平洋海嘯消息發布時", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "其他通知", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "重大", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "晴有霾", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "晴有靄", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "晴有閃電", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "晴有霧", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "晴有雨", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "晴有雨雪", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "晴有大雪", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "晴有雪珠", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "晴有冰珠", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "晴有陣雪", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴陣雨雪", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "晴有雹", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "晴有雷雨", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴有雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴有雷雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "晴大雷雨", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "晴大雷雹", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "晴天伴有雷", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "多雲", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "多雲有霾", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "多雲有靄", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "多雲有閃電", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "多雲有霧", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "多雲有雨", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "多雲有雨雪", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "多雲有大雪", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "多雲有雪珠", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "多雲有冰珠", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "多雲有陣雪", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "多雲陣雨雪", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "多雲有雹", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "多雲有雷雨", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "多雲有雷雪", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "多雲有雷雹", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "多雲大雷雨", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "多雲大雷雹", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "多雲伴有雷", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "陰有霾", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "陰有靄", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "陰有閃電", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "陰有霧", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "陰有雨", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "陰有雨雪", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "陰有大雪", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "陰有雪珠", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "陰有冰珠", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "陰有陣雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "陰陣雨雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "陰有雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "陰有雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "陰有雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "陰有雷雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "陰大雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "陰大雷雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "陰天伴有雷", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "取得天氣異常", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "平均", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "雷達合成回波", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "已結束", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "生效中", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "儲存圖片時發生錯誤:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "發生錯誤:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(最終)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1級", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2級", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3級", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4級", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7級", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "點擊設定所在地", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 觀測網實測震度", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "使用 JMA 震度標準 (0.3秒三分量合成加速度)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "沒有有效資料可顯示", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH時", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "排行榜", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "資料時間:{time}\n共 {ranked_length} 觀測點", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "依", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "降冪", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "升冪", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "合併至", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "сохранение", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24小時{type}趨勢", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "省電策略", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "自動化啟動", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - } -} \ No newline at end of file diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb deleted file mode 100644 index 5a2216506..000000000 --- a/lib/l10n/app_vi.arb +++ /dev/null @@ -1,1801 +0,0 @@ -{ - "@@locale": "vi", - "@@context": "App level localization strings.", - "datetime_format": "MM/dd/yyyy HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "MM/dd/yyyy", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "Trang chủ", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "giám sát động đất", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "Thông báo tin động đất", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "Bản đồ", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "Tôi", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "Cài đặt", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "Chỉnh sửa cách thức hoạt động của DPIP.", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "quyên tặng", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "Theo dõi chúng tôi trên Threads!", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "Phát trực tiếp trên YouTube", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "Máy chủ dịch vụ", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "Giấy phép gói phần mềm của bên thứ ba", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "Độ lớn M {magnitude} Độ sâu {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "Động đất đáng chú ý có mã báo cáo # {reportNumber}", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "Động đất nhẹ, cảm nhận được ở khu vực nhỏ", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "Trang báo cáo", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "Ngày giờ nhận biết động đất", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "nằm ở", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "Cường độ", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "Độ sâu chấn tiêu", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "Bản đồ báo cáo động đất", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "Bản đồ cường độ địa chấn", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "Bản đồ gia tốc mặt đất tối đa", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "Bản đồ vận tốc mặt đất tối đa", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "Cường độ địa chấn tại các khu vực", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "Ngôn ngữ", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "thiết lập ngôn ngữ hiển thị DPIP", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "Ngôn ngữ hiển thị", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "Đã dịch {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "Đã hiệu đính {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "Hỗ trợ biên dịch", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "Nhấp vào đây để giúp chúng tôi cải thiện bản dịch DPIP", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "Tạm thời không thể lấy dữ liệu cảnh báo động đất", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "Hiện không có cảnh báo động đất nào có hiệu lực.", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "Cảnh báo động đất sớm", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "Cảnh báo động đất sớm", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "Dự đoán vị trí", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "Sóng địa chấn", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "không rõ", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "đến", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "đến trong 5 giây", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "phát lại", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "Lưu trữ hình", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "Đã lưu ảnh", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "Cá nhân hóa", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "Chủ đề", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "Điều chỉnh giao diện và màu sắc tổng thể của DPIP", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "Sáng", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "Tối", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "Theo chủ đề hệ thống", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "Vị trí", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "Vị Trí Hiện Tại", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "Điều chỉnh vị trí để nhận thông tin thời tiết theo thời gian thực, dự đoán cường độ động đất và thời gian sóng địa chấn dự kiến đến.", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "Bật định vị tự động", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "Tính năng định vị tự động sẽ sử dụng GPS trên thiết bị của bạn để tự động cập nhật vị trí của bạn dựa trên vị trí địa lý, cung cấp thông tin thời tiết và động đất theo thời gian thực, giúp bạn luôn nắm bắt được tình hình mới nhất tại địa phương.", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "Chưa được thiết lập", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "Quận", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "Thị trấn", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "Chọn vị trí", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "Sao chép FCM Token", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "Đã sao chép FCM Token", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "Trận động đất này có thể gây ra một số biến động trên mặt biển.", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "Trận động đất này có thể gây ra sóng thần. Hãy chú ý theo dõi thông tin cập nhật.", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "Đã xảy ra lỗi khi lấy báo cáo động đất. Vui lòng kiểm tra kết nối mạng và thử lại.", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "版本 {version}\n組建 {buildNumber}\n由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "Ngôn ngữ nguồn", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "Kiểm tra thông báo", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "Kiểm tra thông báo âm thanh về thông tin thời tiết thời gian thực, báo cáo động đất, v. v.", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 4 以上", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "偵測到晃動", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "所在地(縣市)實測震度 3 以上", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "Âm thanh cảnh báo động đất nhanh", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "Thông tin động đất", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "Khác", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "Cảnh báo sóng thần (Cảnh báo)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "海嘯警報發布時\n沿海地區鄉鎮", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "Cảnh báo sóng thần (Cẩn thận)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "海嘯警報發布時\n上述除外地區", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "發送公告時", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "Danh sách bản đồ", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "Hình ảnh radar", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "Lượng mưa", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "Nhiệt độ", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "Độ ẩm", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "Áp suất khí quyển", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "Hướng gió/Tốc độ gió", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "gio bảo", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "Thông tin sóng thần", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "Chú thích", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "Đơn vị đo: dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "Đơn vị đo: mm", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "Đơn vị đo: độ C", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "Đơn vị đo: Độ ẩm tương đối", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "Đơn vị đo: hPa", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "Lịch sử", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "Thông tin về các sự kiện lịch sử trong vòng 3 ngày", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "Không có thông tin về các sự kiện lịch sử.", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "Thông tin về các sự kiện hiện tại", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "Hiện không có thông tin về sự kiện nào.", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "Bản tin số {serial}", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "Tia sét", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "Không còn hoạt động", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "Ngoài khu vực dịch vụ, chỉ có sẵn ở các địa điểm khác nhau trên khắp Đài Loan.", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "Không thể nhận được quyền thông báo", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "Thử lại", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "không thể có được quyền truy cập vị trí", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "Hủy bỏ", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "Mùa hè", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "Ngày nhiều mây", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "Thêm", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "Danh sách các tính năng khác", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "Nói chung", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "Gỡ lỗi", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech Website chính thức", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "Bản ghi đẩy thông báo di động", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "Tính năng nâng cao", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "Điều chỉnh các tính năng nâng cao của DPIP", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "Giám sát động đất mạnh", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "Không có thông tin về sóng thần", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "Cảnh báo sóng thần", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "Số {id}, Báo cáo số {serial}", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "Quán rượu", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "Cập nhật", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "Cứu trợ", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "Thời gian dự kiến ​​đến và độ cao của sóng thần", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "Sóng thần được quan sát ở nhiều nơi", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "Thời gian xảy ra", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "Kích cỡ", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "Độ sâu", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "Mọi việc đều an toàn, không có sự cố nào xảy ra.", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "Nhật ký thay đổi", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3 ngày", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2 ngày", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24 giờ", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12 giờ", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6 giờ", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3 giờ", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1 giờ", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10 phút", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "Hôm nay", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "Chào mừng đến với DPIP", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "Cổng thông tin phòng chống thiên tai", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP là ứng dụng được thiết kế bởi một nhóm địa phương tại Đài Loan, tích hợp thông tin từ TREM-Net (Mạng quan sát động đất thời gian thực Đài Loan) và dữ liệu từ Đài Loan Cơ quan thời tiết trung ương (CWA) để cung cấp một ứng dụng thông tin phòng chống thiên tai tích hợp, duy nhất và tiện lợi.", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "Tiếp theo", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "Chúng tôi là ai?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio là một nhóm gồm hơn 15 Học sinh, phần lớn là những người có độ tuổi trung bình dưới 20. Các thành viên đến từ Đài Loan (Bắc, Trung và Nam), Nhật Bản, Hàn Quốc và Trung Quốc.", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "Chúng tôi đã bắt đầu với những gì", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "Nhóm ban đầu được thành lập bằng cách tuyển dụng một nhóm học sinh có sở thích và năng khiếu về máy tính và công nghệ, sau đó đã phát triển vượt ra ngoài phạm vi trường học và trở thành nhóm như hiện nay.", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "Những điều cần lưu ý", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP sẽ cung cấp nhiều thông tin khác nhau từ ExpTech và Đài Loan Cơ quan Thời tiết Trung ương (CWA), vì vậy hãy lưu ý những điều sau khi sử dụng.", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "Tất cả thông tin phải tuân theo nội dung do Đài Loan Cơ quan Thời tiết Trung ương (CWA) công bố.", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "Tùy thuộc vào trạng thái mạng, trạng thái máy chủ, trạng thái ứng dụng, trạng thái nguồn dữ liệu ngược dòng, v.v., sự cố không nhận được thông tin có thể xảy ra và chúng tôi sẽ cố gắng hết sức để tránh những tình huống như vậy, nhưng chúng tôi không đảm bảo rằng chúng sẽ không xảy ra.", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "Rung lắc mạnh có xu hướng xảy ra ở vị trí của người dùng sớm hơn thông báo.", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "Báo cáo động đất nhanh là những tính toán nhanh và có thể chứa nhiều lỗi, do đó cần phải thận trọng và hiểu rõ.", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "Bất kỳ hành vi nào không được chính thức cho phép đều có thể bị coi là vi phạm pháp luật của Trung Hoa Dân Quốc (Đài Loan), vì vậy hãy đảm bảo tuân thủ các quy định có liên quan.", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "Sự cho phép", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "Chúng tôi luôn ủng hộ người dùng và nỗ lực không ngừng vì quyền riêng tư của họ.", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "Thông báo", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "在重大災害發生時以通知來傳遞即時防災資訊", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "使用定位來自動更新所在地設定,提供當地的即時防災資訊", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "Để lưu trữ hình ảnh trực quan dữ liệu từ Đài Loan Cơ quan thời tiết trung ương (CWA) hoặc ExpTech.", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "Không đồng ý", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "Đồng ý", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "Bạn có thể xem dịch vụ “Strong Earthquake Monitor” từ TREM của ExpTech trong DPIP, vui lòng đọc các điều kiện sau và chọn kích hoạt dịch vụ hay không.", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "Thông tin địa chấn theo thời gian thực hiển thị trong DPIP không phải là thông tin do Đài Loan Cơ quan Thời tiết Trung ương (CWA) cung cấp và do đó có thể không nhất quán với kết quả do CWA quan sát được và phải dựa trên thông tin do CWA công bố.", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "Các điểm quan sát mà “Strong Earthquake Monitor” sử dụng thuộc sở hữu của ExpTech và không được Cơ quan Thời tiết Trung ương (CWA) quản lý, vì vậy, vui lòng không chuyển lỗi hoặc bình luận cho CWA, vì điều này sẽ khiến họ bối rối.", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "“giám sát động đất” được sử dụng trong TREM (Giám sát động đất theo thời gian thực tại Đài Loan.) như một chức năng hiển thị địa chấn thời gian thực để quan sát rung động hiện tại trên khắp Đài Loan. Khi động đất xảy ra, sự lan truyền của sóng địa chấn có thể được quan sát thông qua sự thay đổi màu sắc của các điểm quan sát.", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "Do ảnh hưởng của tiếng ồn hàng ngày (ô tô, nhà máy, xây dựng, v.v.), màu sắc của các điểm quan sát cũng có thể thay đổi trong thời gian bình thường. Ngoài ra, vì đây là dữ liệu thời gian thực nên không thể xác định được có trục trặc hay không tại thời điểm này, do đó có thể màu sắc có thể thay đổi do trục trặc của điểm quan sát.", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "Vào đầu tháng 6 năm 2022, chúng tôi đã bắt đầu quan sát các điểm trên khắp Đài Loan. TREM-Net (Mạng lưới quan sát địa chấn TREM) bao gồm hai mạng lưới quan sát, SE-Net (Mạng lưới quan sát địa chấn mạnh, “Gia tốc kế”) và MS-Net (Mạng lưới quan sát vi địa chấn, “Máy đo tốc độ”), cùng nhau ghi lại nhiều dữ liệu khác nhau trong các trận động đất.", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "Khám phá phiên bản mới", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "Vui lòng cập nhật lên phiên bản mới nhất để có trải nghiệm tốt nhất", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "Phiên bản hiện tại", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "Phiên bản mới nhất", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "Cập nhật ngay", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "Bây giờ", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "Cập nhật hoàn tất", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "Cập nhật DPIP đã hoàn tất, bạn có muốn kiểm tra nhật ký thay đổi không?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "Để sau", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "Đi xem", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "Thông báo", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "Hiện tại có thông báo mới, bạn có muốn xem không?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "Không có thông báo bây giờ", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "Người đóng góp", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "Không thể tải nhật ký thay đổi, vui lòng thử lại sau.", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "Không có nhật ký thay đổi bây giờ", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "Thông báo Chi Tiết", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "Phiên bản Chi Tiết", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "không thể có được quyền truy cập", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "Đã xảy ra lỗi khi lưu hình ảnh.", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "Xác nhận", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "Không hiện kết quả tìm kiếm", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "Luôn cho phép", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "Luôn luôn", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "Để có trải nghiệm vị trí tự động tốt hơn, bạn cần phải thiết lập “quyền tự động khởi chạy” để cho phép DPIP tự động thiết lập thông tin vị trí ở chế độ nền.", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "Để có trải nghiệm DPIP tốt hơn, bạn cần phải thiết lập “quyền tự động khởi chạy” để cho phép DPIP tiếp nhận thông báo cảnh báo bình thường ở chế độ nền.", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "Tự khởi động sự cho phép", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "Để có trải nghiệm vị trí tự động tốt hơn, bạn cần phải thiết lập “Không hạn chế” để cho phép DPIP tự động thiết lập thông tin vị trí ở chế độ nền.", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "Để có trải nghiệm DPIP tốt hơn, bạn cần phải thiết lập “Không hạn chế” để cho phép DPIP tiếp nhận thông báo cảnh báo bình thường ở chế độ nền.", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "Chế độ nguồn điện thấp", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "Chức năng thông báo đã bị từ chối, vui lòng chuyển đến trang Cài đặt để thiết lập các quyền được phép.", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "自啟動權限已被拒絕,請移至設定允許權限。", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "省電策略已被拒絕,請移至設定允許權限。", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "Yêu cầu để xin phép", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "Người dùng cần phải tự tay vào trang cài đặt để mở các quyền có liên quan.", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "Bạn chưa thiết lập vị trí của mình", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP cần được thiết lập theo vị trí của bạn để hoạt động bình thường. Nhấp vào “Cài đặt” để thiết lập vị trí của bạn và thử lại.", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "Cài đặt", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "Nhật ký ứng dụng", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "Đã xảy ra lỗi khi sao chép Mã thông báo FCM", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "Chú giải cường độ ước tính", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "Chỉ được sử dụng trong cảnh báo động đất", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5⁻", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5⁺", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6⁻", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6⁺", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "Trong vòng 5 phút sét đánh xuống đất", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "Trong vòng 10 phút sét đánh xuống đất", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "Trong vòng 30 phút sét đánh xuống đất", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "Trong vòng 60 phút sét đánh xuống đất", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "Trong vòng 5 phút tia chớp trên mây", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "Trong vòng 10 phút tia chớp trên mây", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "Trong vòng 30 phút tia chớp trên mây", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "Trong vòng 60 phút tia chớp trên mây", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "Bất thường", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "Kết nối mạng hoặc máy chủ có vấn đề.", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "Thử lại", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "Vui lòng vào Cài đặt ứng dụng để tìm và cấp quyền “Ảnh và phương tiện” rồi thử lại.", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "Không có lịch sử thông báo", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "Khẩn cấp", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "Chi tiết thông báo", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "Thông báo khu vực gửi", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "Thông báo khẩn cấp", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "Thông cáo chung", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "Vui lòng vào Cài đặt ứng dụng để tìm và cấp quyền “Thông báo” rồi thử lại.", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "Vui lòng vào Cài đặt ứng dụng để tìm và cấp quyền “Vị trí” rồi thử lại.", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "Không có dữ liệu có sẵn", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "Trang này trình bày tổng quan về trạng thái của máy chủ tại nhiều thời điểm khác nhau. Dữ liệu thô được cập nhật sau mỗi 5 giây và phiên bản cô đọng được hiển thị tại đây để tối ưu hóa việc sử dụng mạng. Xin lưu ý rằng thông tin này chỉ mang tính tham khảo và trạng thái thực tế phải dựa trên thông báo.", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "Tất cả đều bình thường", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "Tất cả đều bất thường", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "Sự bất thường một phần", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "Bình thường", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "Không ổn định", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "Không có dữ liệu", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "Tự động định vị tiền cảnh", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "Vĩ độ nam {lat_abs}", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "Vĩ độ bắc {lat}", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "Kinh độ tây {lon_abs}", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "Kinh độ đông {lon}", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "Độ trễ: {serviceStatus_count} s", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "Những gì các nhà phát triển muốn nói", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "關於", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "警報區域", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "預估最大震度", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "發震", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "未啟用強震監視器", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "請至設定進階功能中開啟強震監視器。", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "點擊查看提示資訊", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "最高", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "最低", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": " (未啟用)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "簡介", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "營利模式", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "營利真的太難了", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "為什麼不採用廣告?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "對大眾收費?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "如果植入廣告行不通,那對大眾收費呢?變成付費軟體?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "如何營利?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP 開發者的話", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "獲取公告時發生錯誤:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "無效操作", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "操作間隔過短,請稍後再嘗試。", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "知道了", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "錯誤: 無法取得 FCM Token", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "獲取通知紀錄時發生錯誤", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "位置權限", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "錯誤:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "降水量", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "全國", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "歡迎頁面", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "幫助我們維護伺服器的穩定和長久發展", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "最大震度", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "全部", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "篩選器", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "重置", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "套用", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "到底了", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "發送時間", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "有效至", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "影響區域", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "緊急地震速報(重大)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "緊急地震速報(一般)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "緊急地震速報(無聲)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "地震速報(重大)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "所在地(鄉鎮)預估震度 4 以上", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "地震速報(一般)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "所在地(鄉鎮)預估震度 2 以上", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "地震速報(無聲)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "所在地(鄉鎮)預估震度 1 以上", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "震度速報(一般)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "所在地(鄉鎮)實測震度 3 以上", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "震度速報(無聲通知)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "所在地(鄉鎮)實測震度 1 以上", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "強震監視器(一般)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "地震報告(一般)", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "地震報告(無聲通知)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "所在地(縣市)實測震度 1 以上", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "氣象警報", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "雷雨即時訊息", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "天氣警特報", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "所在地(鄉鎮)發布雷雨即時訊息或\n山區暴雨時", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "所在地(鄉鎮)發布紅色燈號之\n天氣警特報", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "所在地(鄉鎮)發布上述除外燈號之\n天氣警特報", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "災害資訊", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "避難資訊", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "所在地(鄉鎮)發布避難警訊時", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "所在地(鄉鎮)發布避難資訊時", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "太平洋海嘯消息(無聲通知)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "太平洋海嘯消息發布時", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "其他通知", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "重大", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "晴有霾", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "晴有靄", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "晴有閃電", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "晴有霧", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "晴有雨", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "晴有雨雪", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "晴有大雪", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "晴有雪珠", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "晴有冰珠", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "晴有陣雪", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴陣雨雪", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "晴有雹", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "晴有雷雨", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴有雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴有雷雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "晴大雷雨", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "晴大雷雹", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "晴天伴有雷", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "多雲", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "多雲有霾", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "多雲有靄", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "多雲有閃電", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "多雲有霧", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "多雲有雨", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "多雲有雨雪", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "多雲有大雪", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "多雲有雪珠", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "多雲有冰珠", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "多雲有陣雪", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "多雲陣雨雪", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "多雲有雹", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "多雲有雷雨", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "多雲有雷雪", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "多雲有雷雹", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "多雲大雷雨", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "多雲大雷雹", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "多雲伴有雷", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "陰有霾", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "陰有靄", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "陰有閃電", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "陰有霧", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "陰有雨", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "陰有雨雪", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "陰有大雪", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "陰有雪珠", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "陰有冰珠", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "陰有陣雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "陰陣雨雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "陰有雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "陰有雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "陰有雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "陰有雷雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "陰大雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "陰大雷雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "陰天伴有雷", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "取得天氣異常", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "平均", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "雷達合成回波", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "已結束", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "生效中", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "儲存圖片時發生錯誤:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "發生錯誤:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(最終)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1級", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2級", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3級", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4級", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7級", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "點擊設定所在地", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 觀測網實測震度", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "使用 JMA 震度標準 (0.3秒三分量合成加速度)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "沒有有效資料可顯示", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH時", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "排行榜", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "資料時間:{time}\n共 {ranked_length} 觀測點", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "依", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "降冪", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "升冪", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "合併至", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "Lưu trữ hình", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24小時{type}趨勢", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "Chế độ nguồn điện thấp", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "自動化啟動", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - } -} \ No newline at end of file diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb deleted file mode 100644 index b85462ff5..000000000 --- a/lib/l10n/app_zh.arb +++ /dev/null @@ -1,1732 +0,0 @@ -{ - "@@locale": "zh", - "@@context": "App level localization strings.", - "datetime_format": "yyyy/MM/dd HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "yyyy/MM/dd", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "首頁", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "強震監視器", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "地震報告", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "地圖", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "我", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "設定", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "調整 DPIP 的運作方式。", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "贊助我們", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "在 Threads 上追蹤我們", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "YouTube 直播", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "伺服器狀態", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "第三方套件授權", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "M {magnitude} 深度 {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "編號 {reportNumber} 顯著有感地震", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "小區域有感地震", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "報告頁面", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "發震時間", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "位於", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "地震規模", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "震源深度", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "地震報告圖", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "震度圖", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "最大地動加速度圖", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "最大地動速度圖", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "各地震度", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "語言", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "調整 DPIP 的顯示語言", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "顯示語言", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "已翻譯 {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "已校對 {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "協助翻譯", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "點擊這裡來幫助我們改進 DPIP 的翻譯", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "暫時無法取得地震速報資料", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "目前無生效中的地震速報", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "地震速報", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "緊急地震速報", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "所在地預估", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "震波", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "未知", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "抵達", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "秒後抵達", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "重播", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "儲存", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "已儲存圖片", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "個人化", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "主題色", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "調整 DPIP 整體的外觀與顏色", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "淺色", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "深色", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "跟隨系統主題", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "位置", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "所在地", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "調整所在地來接收即時天氣資訊、地震預估震度以及地震波預估抵達秒數等", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "啟用自動定位", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "自動定位功能將使用您的裝置上的 GPS ,根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "尚未設定", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "縣市", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "鄉鎮", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "選擇所在地", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "複製 FCM Token", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "已複製 FCM Token", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "此地震可能引起若干海面變動", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "此地震可能引起海嘯 注意後續資訊", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "取得地震報告時發生錯誤,請檢查網路狀況後再試一次。", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "版本 {version}\n組建 {buildNumber}\n由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "來源語言", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "通知測試", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "測試即時天氣資訊、地震速報等音效通知", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 4 以上", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "偵測到晃動", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "所在地(縣市)實測震度 3 以上", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "地震速報音效", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "地震資訊", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "其他", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "海嘯警報(警報)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "海嘯警報發布時\n沿海地區鄉鎮", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "海嘯警報(注意)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "海嘯警報發布時\n上述除外地區", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "發送公告時", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "地圖列表", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "雷達回波", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "降水", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "氣溫", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "濕度", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "氣壓", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "風向/風速", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "颱風", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "海嘯資訊", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "圖例", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "單位:dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "單位:毫米 (mm)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "單位:攝氏度 (°C)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "單位:相對濕度 (%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "單位:百帕 (hPa)", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "歷史", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "3天內的歷史事件資訊", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "沒有歷史事件資訊", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "目前的事件資訊", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "目前沒有事件資訊", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "第 {serial} 報", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "閃電", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "服務區域外", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "服務區域外,僅在臺灣各地可用", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "無法取得通知權限", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "再試一次", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "無法取得位置權限", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "取消", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "晴", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "陰", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "更多", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "更多功能列表", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "一般", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "除錯", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech 官網", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "行動通知推播紀錄", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "進階功能", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "調整 DPIP 的進階功能", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "啟用強震監視器", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "近期無海嘯資訊", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "海嘯警報", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "{id}號 第{serial}報", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "發布", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "更新", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "解除", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "預估海嘯到達時間及波高", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "各地觀測到的海嘯", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "發生時間", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "規模", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "深度", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "一切平安,無事件發生。", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "更新日誌", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3天", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3天" - }, - "interval_2_days": "2天", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2天" - }, - "interval_24_hours": "24小時", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24小時" - }, - "interval_12_hours": "12小時", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12小時" - }, - "interval_6_hours": "6小時", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6小時" - }, - "interval_3_hours": "3小時", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3小時" - }, - "interval_1_hour": "1小時", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1小時" - }, - "interval_10_minutes": "10分鐘", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10分鐘" - }, - "interval_now": "今日", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "歡迎使用 DPIP", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "防災資訊平台", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "下一步", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "我們是誰?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "我們的初衷", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "注意事項", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "任何資訊應以中央氣象署發布之內容為準。", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "強烈搖晃有機率比通知早抵達使用者所在地。", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "權限", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "我們一直和使用者站在一起,為使用者的隱私而不斷努力。", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "通知", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "用於提供通知服務", - "@notification_service_description": { - "description": "「歡迎」頁面 → 用於提供通知服務" - }, - "location_based_service": "用於提供基於位置的服務", - "@location_based_service": { - "description": "「歡迎」頁面 → 用於提供基於位置的服務" - }, - "data_visualization_storage": "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "不同意", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "同意", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "發現新版本", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "更新至最新版本以獲得最佳體驗", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "目前版本", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "最新版本", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "立即更新", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "暫時略過", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "更新完成", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIP 更新完成,要前往查看更新日誌嗎?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "稍後再說", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "前往查看", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "公告", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "有新的公告,要前往查看嗎?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "目前沒有公告", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "貢獻者", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "無法載入更新日誌,請稍後再試。", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "目前沒有更新日誌", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "公告詳情", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "版本詳情", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "無法取得權限", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "儲存圖片時發生錯誤", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "確定", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "無搜尋結果", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "一律允許", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "永遠", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "自啟動權限", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "省電策略", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "通知功能已被拒絕,請移至設定允許權限。", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "permission_request": "權限請求", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "需要使用者手動到設定開啟相關權限。", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "尚未設定所在地", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP 需要設定所在地才能正常運作。點擊「前往設定」設定所在地後再試一次。", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "前往設定", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "App 日誌", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "複製 FCM Token 時發生錯誤", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "預估震度圖例", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "僅用於地震速報時", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5弱", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5強", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6弱", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6強", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "5 分鐘內對地閃電", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "10 分鐘內對地閃電", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "30 分鐘內對地閃電", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "60 分鐘內對地閃電", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "5 分鐘內雲間閃電", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "10 分鐘內雲間閃電", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "30 分鐘內雲間閃電", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "60 分鐘內雲間閃電", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "異常", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "網路連線或伺服器異常。", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "重試", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "沒有通知紀錄", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "緊急", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "通知詳細資訊", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "通知發送區域", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "緊急通知", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "一般通知", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "請您到應用程式設定中找到並允許「通知」權限後再試一次。", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "請您到應用程式設定中找到並允許「位置」權限後再試一次。", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "沒有可用的資料", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "全部正常", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "全部異常", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "部分異常", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "正常", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "不穩定", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "無資料", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "前景自動定位", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "南緯 {lat_abs} 度", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "北緯 {lat} 度", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "西經 {lon_abs} 度", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "東經 {lon} 度", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "延遲: {serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "開發者想說的話", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "關於", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "警報區域", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "預估最大震度", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "發震", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "未啟用強震監視器", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "請至設定進階功能中開啟強震監視器。", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "點擊查看提示資訊", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "最高", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述" - }, - "lowest": "最低", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述" - }, - "not_enabled": " (未啟用)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "簡介", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "營利模式", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "營利真的太難了", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "為什麼不採用廣告?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "對大眾收費?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "如果植入廣告行不通,那對大眾收費呢?變成付費軟體?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "如何營利?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP 開發者的話", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "獲取公告時發生錯誤:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "無效操作", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "操作間隔過短,請稍後再嘗試。", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "知道了", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "錯誤: 無法取得 FCM Token", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "獲取通知紀錄時發生錯誤", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "位置權限", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "錯誤:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "降水量", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "全國", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "歡迎頁面", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "幫助我們維護伺服器的穩定和長久發展", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "最大震度", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "全部", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "篩選器", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "重置", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "套用", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "到底了", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "發送時間", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "有效至", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "影響區域", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "緊急地震速報(重大)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "緊急地震速報(一般)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "緊急地震速報(無聲)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "地震速報(重大)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "所在地(鄉鎮)預估震度 4 以上", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "地震速報(一般)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "所在地(鄉鎮)預估震度 2 以上", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "地震速報(無聲)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "所在地(鄉鎮)預估震度 1 以上", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "震度速報(一般)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "所在地(鄉鎮)實測震度 3 以上", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "震度速報(無聲通知)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "所在地(鄉鎮)實測震度 1 以上", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "強震監視器(一般)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "地震報告(一般)", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "地震報告(無聲通知)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "所在地(縣市)實測震度 1 以上", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "氣象警報", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "雷雨即時訊息", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "天氣警特報", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "所在地(鄉鎮)發布雷雨即時訊息或\n山區暴雨時", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "所在地(鄉鎮)發布紅色燈號之\n天氣警特報", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "所在地(鄉鎮)發布上述除外燈號之\n天氣警特報", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "災害資訊", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "避難資訊", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "所在地(鄉鎮)發布避難警訊時", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "所在地(鄉鎮)發布避難資訊時", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "太平洋海嘯消息(無聲通知)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "太平洋海嘯消息發布時", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "其他通知", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "重大", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "晴有霾", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "晴有靄", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "晴有閃電", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "晴有霧", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "晴有雨", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "晴有雨雪", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "晴有大雪", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "晴有雪珠", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "晴有冰珠", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "晴有陣雪", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴陣雨雪", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "晴有雹", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "晴有雷雨", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴有雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴有雷雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "晴大雷雨", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "晴大雷雹", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "晴天伴有雷", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "多雲", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "多雲有霾", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "多雲有靄", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "多雲有閃電", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "多雲有霧", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "多雲有雨", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "多雲有雨雪", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "多雲有大雪", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "多雲有雪珠", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "多雲有冰珠", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "多雲有陣雪", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "多雲陣雨雪", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "多雲有雹", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "多雲有雷雨", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "多雲有雷雪", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "多雲有雷雹", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "多雲大雷雨", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "多雲大雷雹", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "多雲伴有雷", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "陰有霾", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "陰有靄", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "陰有閃電", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "陰有霧", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "陰有雨", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "陰有雨雪", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "陰有大雪", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "陰有雪珠", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "陰有冰珠", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "陰有陣雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "陰陣雨雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "陰有雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "陰有雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "陰有雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "陰有雷雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "陰大雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "陰大雷雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "陰天伴有雷", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "取得天氣異常", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "平均", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "雷達合成回波", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "已結束", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "生效中", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "儲存圖片時發生錯誤:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "發生錯誤:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(最終)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1級", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2級", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3級", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4級", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7級", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "點擊設定所在地", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 觀測網實測震度", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "使用 JMA 震度標準 (0.3秒三分量合成加速度)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "沒有有效資料可顯示", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH時", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - } -} \ No newline at end of file diff --git a/lib/l10n/app_zh_CN.arb b/lib/l10n/app_zh_CN.arb deleted file mode 100644 index df577b6ce..000000000 --- a/lib/l10n/app_zh_CN.arb +++ /dev/null @@ -1,1801 +0,0 @@ -{ - "@@locale": "zh_CN", - "@@context": "App level localization strings.", - "datetime_format": "yyyy/MM/dd HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "yyyy/MM/dd", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "首页", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "强震监视器", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "地震报告", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "地图", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "我", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "设置", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "调整 DPIP 的运行方式", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "赞助我们", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "在Threads关注我们", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "YouTube 直播", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "服务器状态", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "第三方套件授权", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "震级 {magnitude} 深度 {depth} 千米", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "序号 {reportNumber} 显著有感地震", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "小区域有感地震", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "报告详情", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "发震时刻", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "位于", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "地震震级", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "震源深度", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "地震报告图", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "震度图", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "峰值地震动加速度图", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "峰值最大地震动速度图", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "各地震度", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "语言", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "更改 DPIP 的显示语言", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "显示语言", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "已翻译 {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "已校对 {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "协助翻译", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "点击这里来帮助我们改进 DPIP 的翻译", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "暂时无法取得地震预警资料", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "目前无生效中的地震预警", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "地震预警", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "紧急地震预警", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "本地震度", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "震波", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "未知", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "抵达", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "秒后抵达", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "回放", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "储存", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "图片已储存", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "个性化", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "主题色", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "调整 DPIP 整体的外观与颜色", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "浅色", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "深色", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "跟随系统主题", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "位置", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "所在地", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "调整所在地来接收即时天气信息、地震预估震度以及地震波预估抵达秒数等", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "启用自动定位", - "@settings_location_auto": { - "description": "「設定」路徑 → 「啟用自動定位」標題" - }, - "settings_location_auto_description": "自动定位功能将使用您的装置上的定位功能 ,根据您的地理位置,自动更新您的所在地,提供实时的天气和地震资讯,让您随时掌握当地最新状况。", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "尚未设置", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "县市", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "乡镇市区", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "选择所在地", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "复制 FCM Token", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "已复制 FCM Token", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "此地震可能引起若干海面变动", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "此地震可能引起海啸 注意后续信息", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "获取地震报告时发生错误,请检查网络连接后再试一次。", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "版本 {version}\n构建 {buildNumber}\n由 ExpTech 探索科技制作\n部分资料来源 CWA(中央气象署)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "来源语言", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "通知测试", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 通知測試" - }, - "notify_test_description": "测试实时天气信息、地震预警等音效通知", - "@notify_test_description": { - "description": "「我」路徑 → 「通知測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "最大震度 5 弱以上 且\n所在地(乡镇)预估震度 4 以上", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "最大震度 5 弱以上 且\n所在地(乡镇)预估震度 2 以上", - "@eew_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "侦测到晃动", - "@eq_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "所在地(县市)实测震度 3 以上", - "@report_description_sound": { - "description": "「我」路徑 → 「通知測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "地震预警音效", - "@eew_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "地震信息", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「通知測試」內容 → 地震資訊" - }, - "other_title": "其他", - "@other_title": { - "description": "「我」路徑 → 「通知測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "海啸警报(警报)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "海啸警报发布时\n沿海地区乡镇", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "海啸警报(注意)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "海啸警报发布时\n上述除外地区", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "发送公告时", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「通知測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "地图目录", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "雷达拼图", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "降水", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "气温", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "湿度", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "气压", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "风向/风速", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "台风", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "海嘯信息", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "图例", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "单位:dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "单位:毫米(mm)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "单位:摄氏度(°C)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "单位:相对湿度 (%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "单位:百帕 (hPa)", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "历史", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "3天内的历史事件信息", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "没有历史事件信息", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "当前事件信息", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "当前没有事件信息", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "第 {serial} 报", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "雷电", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "服务区域外", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "服务区域外,仅在台湾各地可用", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "无法获取通知权限", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "再试一次", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "无法获取位置权限", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "取消", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "晴", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "阴", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "更多", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "更多功能列表", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "常规​​​​​", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "调试", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech 官网", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "通知推送记录", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "高级选项", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "调整 DPIP 的高级选项", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "启用强震监视器", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "近期无海啸信息", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "海啸警报", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "{id}号 第{serial}报", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "发布", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "更新", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "解除", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "预估海啸到达时间及波高", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "各地观测到的海啸", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "发生时间", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "震级", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "深度", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "一切平安,无事件发生。", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "更新日志", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3 天", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2 天", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24 小时", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12 小时", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6 小时", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3 小时", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1 小时", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10 分钟", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "今天", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "欢迎使用 DPIP", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "防灾信息平台", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP 是一款由台湾本土团队设计的 App,集成 TREM-Net (台湾即时地震观测网) 的信息及中央气象署数据,提供一个集成、单一且便利的防灾信息应用。", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "下一步", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "我们是谁?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio 是一群大部分由学生组成,平均年龄未满 20 岁、人数超过 15 + 的团体。成员来自台湾北中南、日本、韩国、中国的学生。", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "我们的初衷", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "成立初衷是招募一群对计算机及科技有兴趣及能力的同学,后来发展至校外,并逐渐形成现在的样子。", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "注意事项", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP 会传输来自 ExpTech 及中央气象署的各种信息,使用时请注意以下几点。", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "任何信息应以中央气象署发布内容为准。", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "根据网络状态、服务器状态、应用程序状态、上游数据来源状态等,有收不到信息的可能性,我们会尽力避免此类情况,但不保证一定不会发生。", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "强烈摇晃有概率比通知早抵达用户所在地。", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "地震速报为快速计算之结果,可能存在较大误差,应理解并谨慎使用。", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "任何不被官方所认可的行为均有可能承担法律风险,请务必遵守相关规范。", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "权限", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "我们一直和用户站在一起,为用户的隐私而不断努力。", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "通知", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "在重大灾害发生时以通知来传递即时防灾信息", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "使用定位来自动更新所在地设置,提供当地的即时防灾信息", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "用于存储中央气象署或 ExpTech 提供之数据可视化图片", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "不允许", - "@disagree": { - "description": "「歡迎」頁面 → 強震監視器 → 不同意" - }, - "agree": "接受", - "@agree": { - "description": "「歡迎」頁面 → 強震監視器 → 同意" - }, - "trem_service_description": "在 DPIP 中可以查看来自 ExpTech 旗下 TREM 之强震监视器服务,请详细阅读以下条件,并选择是否激活。", - "@trem_service_description": { - "description": "「歡迎」頁面 → 在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "显示的即时震度不是中央气象署所提供之资料,因此可能与中央气象署观测到的结果不一致,应以中央气象署公布之资讯为主。", - "@real_time_magnitude_warning": { - "description": "「歡迎」頁面 → 顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "强震监视器使用的测站为 ExpTech 所有,不归中央气象署管理,请不要向中央气象署交付故障或意见,会造成他们的困扰。", - "@trem_station_warning": { - "description": "「歡迎」頁面 → 強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "强震监视器是由 TREM(台湾即时地震监测)观测到全台现在的震动,做为即时震度显示的功能,地震发生当下可以透过站点颜色变化,观察地震波传播情形。", - "@trem_monitor_description": { - "description": "「歡迎」頁面 → 強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "由于日常杂讯(汽车、工厂、施工等)影响,平时站点可能也会有颜色变化。另外,由于是即时数据,当下无法判断是否是故障,所以也有可能因为站点故障而改变颜色。", - "@station_noise_warning": { - "description": "「歡迎」頁面 → 由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "2022 年6 月初开始于全台各地部署站点,TREM-Net(TREM 地震观测网)由两个观测网组成,分别为SE-Net(强震观测网「加速度仪」)及MS-Net(微震观测网「速度仪」),共同纪录地震时的各项数据。", - "@trem_net_deployment": { - "description": "「歡迎」頁面 → 2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "发现新版本", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "更新至最新版本以获得最佳体验", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "当前版本", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "最新版本", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "立即更新", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "暂时跳过", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "更新完成", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIP 更新完成,要前往查看更新日志吗?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "稍后再说", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "前往查看", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "公告", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "有新的公告,要前往查看吗?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "目前没有公告", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "贡献者", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "无法载入更新日志,请稍后再试。", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "目前没有更新日志", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "公告详情", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "版本详情", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "无法获取权限", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "存储图片时发生错误", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "确定", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "无搜索结果", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "始终允许", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "永久", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "为了获得更好的自动定位体验,您需要授予「自启动权限」以便让 DPIP 在后台自动设置所在地信息。", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "为了获得更好的 DPIP 体验,您需要授予「自启动权限」以便让 DPIP 在后台正常接收警报通知。", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "自启动权限", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "为了获得更好的自动定位体验,您需要授予「无限制」以便让 DPIP 在后台自动设置所在地信息。", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "为了获得更好的 DPIP 体验,您需要授予「无限制」以便让 DPIP 在后台有正常接收警讯通知。", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "省电策略", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "通知功能已被拒绝,请移至设置允许权限。", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "自启动权限被拒绝,请前往设置允许权限。", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "省电策略被拒绝,请前往设置允许权限。", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "权限请求", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "需要用户手动前往设置开启相关权限。", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "尚未设定所在地", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP 需要设置所在地才能正常运作。点击「前往设置」设置所在地后再试一次。", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "前往设置", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "App 日志", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "复制 FCM Token 时发生错误", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "预估震度图例", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "仅用于地震预警时", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "weak_5": "5弱", - "@weak_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5弱" - }, - "strong_5": "5强", - "@strong_5": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 5強" - }, - "weak_6": "6弱", - "@weak_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6弱" - }, - "strong_6": "6强", - "@strong_6": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 6強" - }, - "lightning_1_5": "5 分钟内对地雷电", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "10 分钟内对地雷电", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "30 分钟内对地雷电", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "60 分钟内对地雷电", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "5 分钟内云间雷电", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "10 分钟内云间雷电", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "30 分钟内云间雷电", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "60 分钟内云间雷电", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "异常", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "网络连接或服务器异常。", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "重试", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "请您到应用程序设置中找到并允许「照片和媒体」权限后再试一次。", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "没有通知记录", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "紧急", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "通知详细信息", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "通知发送区域", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "紧急通知", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "一般通知", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "请您到应用程序设置中找到并允许「通知」权限后再试一次。", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "请您到应用程序设定中找到并允许「位置」权限后再试一次。", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "没有可用数据", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "此页面呈现服务器各时段状态概览。原始数据每5秒更新一次,此处显示精简版本以优化网络用量。请注意,此信息仅供参考,实际状况应以公告为准。", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "全部正常", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "全部异常", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "部分异常", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "正常", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "不稳定", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "无数据", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "前台自动定位", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "南纬 {lat_abs} 度", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "北纬 {lat} 度", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "西经 {lon_abs} 度", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "东经 {lon} 度", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "延迟:{serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "开发者想说的话", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "关于", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "警报区域", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "预估最大震度", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "发震", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "未启用强震监视器", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "请至设定进阶功能中开启强震监视器。", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "点击查看提示信息", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "最高", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "最低", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": " (未启用)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "简介", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "首先感谢所有下载这个软件的用户,整个开发团队在此献上最诚挚的谢意。", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP 是一个以集成所有防灾信息为目标的软件,希望能成为民众生活中不可或缺的一部分。尽管目前完成度不高且困难重重,但我们仍会持续朝这个目标前进。", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "在开发软件时,我们投入了大量的金钱、时间与精力,在人事成本、设备费用、云端服务、网络费用等项目上,花费超过50万新台币。为此,我们希望获得用户的支持,在不依赖其他第三方公司的前提下,继续维持营运。", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "营利模式", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "为了维持 App 的开发,团队内部进行了多次激烈讨论,思考如何才能营利?我们试图在众多方案中,找出一个适合的营利模式。我们发现,大多数同类型软件采用植入广告的方式来达到营利目的,这使得我们一度考虑采用该方式作为营利的方法。", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "营利真的太难了", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "我们调查了一般民众的付费意愿,发现大部分人普遍防灾意识不足,更不会花钱在这件事情上。后台的数据能侧面证实这个说法,据统计,热心赞助的民众大约是整体用户的10万分之1,这使得植入广告似乎成为了最好的解决方法。", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "为什么不采用广告?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "当灾害发生时,大家一定不会想要看广告吧?这是我们不植入广告的第一个理由。防灾导向的软件,快速正确地传递防灾信息是首要任务。如果因为广告而导致无法正确掌握防灾信息,这反而和我们的理念相违背。况且,灾害发生时通常通信品质不佳,还要额外浪费网络流量在加载广告,这件事太令人沮丧了。", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "对大众收费?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "如果植入广告行不通,那对大众收费呢?变成付费软件?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "首先,作为防灾软件,我们希望尽可能地将防灾信息传递给越多人越好。而且,或许真正需要的人没办法再多出额外的经费承担这项支出,我们希望帮助更多的人。其次,作为开发人员,我们希望软件可以有很多人使用,收费会直接导致大家使用意愿降低。", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "如何营利?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "总结上述,我们希望培养出对防灾有兴趣的人、重视防灾的人,支持我们的软件开发,一起往前发展。", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP 开发者的话", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "获取公告时发生错误:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "无效操作", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "操作间隔过短,请稍后再尝试。", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "知道了", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "错误: 无法取得 FCM Token", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "获取通知纪录时发生错误", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "自动定位功能需要您允许 DPIP 使用通知权限才能正常运作。", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "自动定位功能需要您允许 DPIP 使用位置权限才能正常运作。", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "位置权限", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "为了获得更好的自动定位体验,您需要将位置权限提升至「{permissionType}」以便让 DPIP 在后台自动设置所在地信息。", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "自动定位功能需要将位置权限提升至「{permissionType}」以在后台使用。", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "错误:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "降水量", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "全国", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "欢迎页面", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "帮助我们维护服务器的稳定和长久发展", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "最大震度", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "全部", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "筛选器", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "重置", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "应用", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "到底了", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "发送时间", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "有效至", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "影响区域", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "紧急地震预警(重大)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "紧急地震预警(一般)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "紧急地震预警(无声)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "最大震度 5 弱以上 且\n所在地(乡镇)预估震度 1 以上", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "地震预警(重大)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "所在地(乡镇)预估震度 4 以上", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "地震预警(一般)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "所在地(乡镇)预估震度 2 以上", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "地震预警(无声)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "所在地(乡镇)预估震度 1 以上", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "震度速報(一般)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "所在地(乡镇)实测震度 3 以上", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "震度速報(无声通知)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "所在地(乡镇)实测震度 1 以上", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "强震监视器(一般)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "地震报告(一般)", - "@sound_report_minor": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "地震报告(无声通知)", - "@sound_report_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "所在地(县市)实测震度 1 以上", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "气象警报", - "@sound_weather_warning": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "雷雨即时信息", - "@sound_rain_instant": { - "description": "「我」路徑 → 「通知測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "天气警特报", - "@sound_weather_alert": { - "description": "「我」路徑 → 「通知測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "所在地(乡镇)发布雷雨即时讯息或\n山区暴雨时", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "所在地(乡镇)发布红色灯号之\n天气警特报", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "所在地(乡镇)发布上述除外灯号之\n天气警特报", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "灾害信息", - "@sound_disaster": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "避难信息", - "@sound_evacuation": { - "description": "「我」路徑 → 「通知測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "所在地(乡镇)发布避难警讯时", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "所在地(乡镇)发布避难信息时", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "太平洋海啸消息(无声通知)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "太平洋海啸消息发布时", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「通知測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "其他通知", - "@sound_other_notifications": { - "description": "「我」路徑 → 「通知測試」內容 → 「其他通知」標題 " - }, - "sound_major": "重大", - "@sound_major": { - "description": "「我」路徑 → 「通知測試」內容 → 重大" - }, - "sunny_with_haze": "晴有霾", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "晴有薄雾", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "晴有闪电", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "晴有雾", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "晴有雨", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "晴有雨雪", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "晴有大雪", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "晴有雪珠", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "晴有冰珠", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "晴有阵雪", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴阵雨雪", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "晴有冰雹", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "晴有雷雨", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴有雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴有雷冰雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "晴大雷雨", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "晴大雷冰雹", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "晴天伴有雷", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "多云", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "多云有霾", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "多云有薄雾", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "多云有雷电", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "多云有雾", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "多云有雨", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "多云有雨雪", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "多云有大雪", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "多云有雪珠", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "多云有冰珠", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "多云有阵雪", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "多云阵雨雪", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "多云有冰雹", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "多云有雷雨", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "多云有雷雪", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "多云有雷冰雹", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "多云大雷雨", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "多云大雷冰雹", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "多云伴有雷", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "阴有霾", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "阴有薄雾", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "阴有雷电", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "阴有雾", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "阴有雨", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "阴有雨雪", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "阴有大雪", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "阴有雪珠", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "阴有冰珠", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "阴有阵雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "阴阵雨雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "阴有冰雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "阴有雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "阴有雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "阴有雷冰雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "阴大雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "阴天有强雷冰雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "阴天伴有雷", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "取得天气异常", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "平均", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "雷达合成回波", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "已结束", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "生效中", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "存储图片需要您允许 DPIP 使用相片和媒体权限才能正常运作。", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "存储图片时发生错误:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "发生错误:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(最终)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1级", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2级", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3级", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4级", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7级", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "点击设置所在地", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 观测网实测震度", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "使用 JMA 震度标准 (0.3秒三分量合成加速度)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "本资料由 TREM-Net 观测网自动观测结果所得,尚未经人为检视确认,仅供应变之初步参考。实际应以中央气象署发布的信息为准。", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "没有有效资料可显示", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH时", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "排行榜", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "资料时间:{time}\n共 {ranked_length} 观测点", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "依", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "降序", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "升序", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "合并至", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "储存", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24小时{type}趋势", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "省电策略", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "允许DPIP在后台持续运行,以便实时防灾通知。", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "自启动", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "允许DPIP在设备重启或关闭后自动启动,以持续提供防灾通知服务。", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - } -} \ No newline at end of file diff --git a/lib/l10n/app_zh_TW.arb b/lib/l10n/app_zh_TW.arb deleted file mode 100644 index 9eeb99c90..000000000 --- a/lib/l10n/app_zh_TW.arb +++ /dev/null @@ -1,1826 +0,0 @@ -{ - "@@locale": "zh_TW", - "@@context": "App level localization strings.", - "datetime_format": "yyyy/MM/dd HH:mm:ss", - "@datetime_format": { - "description": "日期時間顯示格式" - }, - "full_date_format": "yyyy/MM/dd (EEEE)", - "@full_date_format": { - "description": "完整日期顯示格式" - }, - "date_format": "yyyy/MM/dd", - "@date_format": { - "description": "日期顯示格式" - }, - "time_format": "HH:mm:ss", - "@time_format": { - "description": "時間顯示格式" - }, - "home": "首頁", - "@home": { - "description": "「首頁」頁面標題" - }, - "monitor": "強震監視器", - "@monitor": { - "description": "「地圖」路徑 → 強震監視器、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 強震監視器" - }, - "report": "地震報告", - "@report": { - "description": "「更多」路徑 → 地震報告、「設定」路徑 → 「通知測試」內容 →「地震資訊」標題 → 地震報告" - }, - "map": "地圖", - "@map": { - "description": "「地圖」頁面標題" - }, - "me": "我", - "@me": { - "description": "「我」頁面標題" - }, - "settings": "設定", - "@settings": { - "description": "「設定」頁面標題" - }, - "settingsDescription": "調整 DPIP 的運作方式。", - "@settingsDescription": { - "description": "「設定」頁面敘述" - }, - "donate": "贊助我們", - "@donate": { - "description": "「我」頁面 → 「贊助我們」按鈕" - }, - "threads": "在 Threads 上追蹤我們", - "@threads": { - "description": "「我」頁面 → 應用程式資訊 → 「在 Threads 上追蹤我們」按鈕" - }, - "youtube": "YouTube 直播", - "@youtube": { - "description": "「我」頁面 → 應用程式資訊 → 「YouTube 直播」按鈕" - }, - "server_status": "伺服器狀態", - "@server_status": { - "description": "「我」頁面 → 應用程式資訊 → 「伺服器狀態」按鈕" - }, - "third_party_libraries": "第三方套件授權", - "@third_party_libraries": { - "description": "「我」頁面 → 應用程式資訊 → 「第三方套件授權」按鈕" - }, - "report_list_item_subtitle": "M {magnitude} 深度 {depth} km", - "@report_list_item_subtitle": { - "description": "「更多」路徑 → 「地震報告列表」頁面 → 地震報告條目 → 副標題", - "placeholders": { - "magnitude": { - "type": "String", - "description": "規模數值" - }, - "depth": { - "type": "String", - "description": "深度數值" - } - } - }, - "report_with_number": "編號 {reportNumber} 顯著有感地震", - "@report_with_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題", - "placeholders": { - "reportNumber": { - "type": "String" - } - } - }, - "report_without_number": "小區域有感地震", - "@report_without_number": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 副標題" - }, - "open_report_url": "報告頁面", - "@open_report_url": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 開啟報告頁面按鈕 → 提示" - }, - "report_event_time": "發震時間", - "@report_event_time": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 發震時間" - }, - "report_location": "位於", - "@report_location": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 位於、「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 位於" - }, - "report_magnitude": "地震規模", - "@report_magnitude": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震規模" - }, - "report_depth": "震源深度", - "@report_depth": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震源深度" - }, - "report_image": "地震報告圖", - "@report_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖" - }, - "report_intensity_image": "震度圖", - "@report_intensity_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 震度圖" - }, - "report_pga_image": "最大地動加速度圖", - "@report_pga_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動加速度圖" - }, - "report_pgv_image": "最大地動速度圖", - "@report_pgv_image": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 最大地動速度圖" - }, - "report_intensity": "各地震度", - "@report_intensity": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 各地震度" - }, - "settings_locale": "語言", - "@settings_locale": { - "description": "「設定」路徑 → 「語言」標題" - }, - "settings_locale_description": "調整 DPIP 的顯示語言", - "@settings_locale_description": { - "description": "「設定」路徑 → 「語言」副標題敘述" - }, - "settings_display_locale": "顯示語言", - "@settings_display_locale": { - "description": "「設定」路徑 → 「顯示語言」標題" - }, - "settings_locale_translated": "已翻譯 {percentage}", - "@settings_locale_translated": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已翻譯百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_approved": "已校對 {percentage}", - "@settings_locale_approved": { - "description": "「設定」路徑 → 「顯示語言」設定 → 語言選項已校對百分比", - "placeholders": { - "percentage": { - "type": "String", - "description": "已翻譯百分比" - } - } - }, - "settings_locale_crowdin": "協助翻譯", - "@settings_locale_crowdin": { - "description": "「設定」路徑 → 「協助翻譯」標題" - }, - "settings_locale_crowdin_description": "點擊這裡來幫助我們改進 DPIP 的翻譯", - "@settings_locale_crowdin_description": { - "description": "「設定」路徑 → 「協助翻譯」副標題敘述" - }, - "earthquake_warning_error": "暫時無法取得地震速報資料", - "@earthquake_warning_error": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 暫時無法取得地震速報資料" - }, - "no_earthquake_warning": "目前無生效中的地震速報", - "@no_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 目前無生效中的地震速報" - }, - "earthquake_warning": "地震速報", - "@earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 地震速報" - }, - "emergency_earthquake_warning": "緊急地震速報", - "@emergency_earthquake_warning": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 緊急地震速報" - }, - "location_estimate": "所在地預估", - "@location_estimate": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 所在地預估" - }, - "seismic_waves": "震波", - "@seismic_waves": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 震波" - }, - "monitor_unknown": "未知", - "@monitor_unknown": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 未知" - }, - "monitor_arrival": "抵達", - "@monitor_arrival": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 抵達" - }, - "monitor_after_seconds": "秒後抵達", - "@monitor_after_seconds": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 秒後抵達" - }, - "report_replay": "重播", - "@report_replay": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 重播按鈕" - }, - "image_save": "儲存", - "@image_save": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片" - }, - "image_saved": "已儲存圖片", - "@image_saved": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊托盤 → 地震報告圖片 → 提示描述" - }, - "settings_Personalization": "個人化", - "@settings_Personalization": { - "description": "「設定」路徑 → 「個人化」標題" - }, - "settings_theme": "主題色", - "@settings_theme": { - "description": "「設定」路徑 → 「主題色」副標題" - }, - "settings_theme_description": "調整 DPIP 整體的外觀與顏色", - "@settings_theme_description": { - "description": "「設定」路徑 → 「主題色」副標題描述" - }, - "theme_light": "淺色", - "@theme_light": { - "description": "「設定」路徑 → 「主題色」設定 → 淺色" - }, - "theme_dark": "深色", - "@theme_dark": { - "description": "「設定」路徑 → 「主題色」設定 → 深色" - }, - "theme_system": "跟隨系統主題", - "@theme_system": { - "description": "「設定」路徑 → 「主題色」設定 → 跟隨系統主題" - }, - "settings_position": "位置", - "@settings_position": { - "description": "「設定」路徑 → 「位置」標題" - }, - "settings_location": "所在地", - "@settings_location": { - "description": "「設定」路徑 → 「所在地」副標題、「歷史」標題頁面 → 降水量" - }, - "settings_location_description": "調整所在地來接收即時天氣資訊、地震預估震度以及地震波預估抵達秒數等", - "@settings_location_description": { - "description": "「設定」路徑 → 「所在地」副標題敘述" - }, - "settings_location_auto": "自動定位", - "@settings_location_auto": { - "description": "「設定」路徑 → 「自動定位」標題" - }, - "settings_location_auto_description": "自動定位功能將使用您的裝置上的 GPS,即使 DPIP 關閉或未在使用時,也會根據您的地理位置,自動更新您的所在地,提供即時的天氣和地震資訊,讓您隨時掌握當地最新狀況。", - "@settings_location_auto_description": { - "description": "「設定」路徑 → 「啟用自動定位」副標題敘述" - }, - "location_Not_set": "尚未設定", - "@location_Not_set": { - "description": "「設定」路徑 → 「所在地」設定 → 尚未設定" - }, - "location_city": "縣市", - "@location_city": { - "description": "「設定」路徑 → 「所在地」設定 → 縣市" - }, - "location_town": "鄉鎮", - "@location_town": { - "description": "「設定」路徑 → 「所在地」設定 → 鄉鎮" - }, - "location_select": "選擇所在地", - "@location_select": { - "description": "「設定」路徑 → 「所在地」設定 → 選擇所在地" - }, - "settings_fcm": "複製 FCM Token", - "@settings_fcm": { - "description": "「我」頁面標題 → 「FCM」標題" - }, - "settings_copy_fcm": "已複製 FCM Token", - "@settings_copy_fcm": { - "description": "「我」頁面標題 → 「FCM」標題 → 提示描述" - }, - "report_offing": "此地震可能引起若干海面變動", - "@report_offing": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起若干海面變動" - }, - "report_tsunami_attention": "此地震可能引起海嘯 注意後續資訊", - "@report_tsunami_attention": { - "description": "「更多」路徑 → 地震報告 → 詳細資訊 → 此地震可能引起海嘯 注意後續資訊" - }, - "report_error": "取得地震報告時發生錯誤,請檢查網路狀況後再試一次。", - "@report_error": { - "description": "「更多」路徑 → 地震報告 → 取得地震報告時發生錯誤,請檢查網路狀況後再試一次。" - }, - "me_version": "版本 {version}\n組建 {buildNumber}\n由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "@me_version": { - "description": "「我」頁面標題 → 版本 {version}\n組建 {buildNumber}由 ExpTech 探索科技製作\n部分資料來源 CWA(中央氣象署)", - "placeholders": { - "version": { - "type": "String" - }, - "buildNumber": { - "type": "String" - } - } - }, - "source_language": "來源語言", - "@source_language": { - "description": "「設定」路徑 → 「顯示語言」設定 → 來源語言" - }, - "notify_test": "音效測試", - "@notify_test": { - "description": "「我」路徑 → 「通知」標題 → 音效測試" - }, - "notify_test_description": "測試即時天氣資訊、地震速報等音效通知", - "@notify_test_description": { - "description": "「我」路徑 → 「音效測試」副標題敘述 → 測試即時天氣資訊、地震速報等音效通知" - }, - "eew_alert_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 4 以上", - "@eew_alert_description_sound": { - "description": "「我」路徑 → 「音效測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上以 且\n所在地(鄉鎮)預估震度 4 以上" - }, - "eew_description_sound": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上", - "@eew_description_sound": { - "description": "「我」路徑 → 「音效測試」內容 →「地震速報音效」副標題敘述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 2 以上" - }, - "eq_description_sound": "偵測到晃動", - "@eq_description_sound": { - "description": "「我」路徑 → 「音效測試」內容 →「地震資訊」副標題敘述 → 偵測到晃動" - }, - "report_description_sound": "所在地(縣市)實測震度 3 以上", - "@report_description_sound": { - "description": "「我」路徑 → 「音效測試」內容 →「地震資訊」副標題敘述 → 所在地(縣市)實測震度 3 以上" - }, - "eew_sound_title": "地震速報音效", - "@eew_sound_title": { - "description": "「我」路徑 → 「音效測試」內容 → 地震速報音效" - }, - "eew_info_sound_title": "地震資訊", - "@eew_info_sound_title": { - "description": "「我」路徑 → 「音效測試」內容 → 地震資訊" - }, - "other_title": "其他", - "@other_title": { - "description": "「我」路徑 → 「音效測試」內容 → 其他、「設定」路徑 → 其他" - }, - "tsunami_alert_sound": "海嘯警報(警報)", - "@tsunami_alert_sound": { - "description": "「設定」路徑 → 「音效測試」內容 →「災害資訊」標題 → 海嘯警報(警報)" - }, - "tsunami_alert_description_sound": "海嘯警報發布時\n沿海地區鄉鎮", - "@tsunami_alert_description_sound": { - "description": "「設定」路徑 → 「音效測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n沿海地區鄉鎮" - }, - "tsunami_alert2_sound": "海嘯警報(注意)", - "@tsunami_alert2_sound": { - "description": "「設定」路徑 → 「音效測試」內容 →「災害資訊」標題 → 海嘯警報(注意)" - }, - "tsunami_alert2_description_sound": "海嘯警報發布時\n上述除外地區", - "@tsunami_alert2_description_sound": { - "description": "「設定」路徑 → 「音效測試」內容 →「災害資訊」標題 → 海嘯警報發布時\n上述除外地區" - }, - "server_announcement_description_sound": "發送公告時", - "@server_announcement_description_sound": { - "description": "「設定」路徑 → 「音效測試」內容 →「其他通知」標題 → 發送公告時" - }, - "monitor_list": "地圖列表", - "@monitor_list": { - "description": "「地圖」路徑 → 地圖列表" - }, - "radar_monitor": "雷達回波", - "@radar_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 雷達回波" - }, - "precipitation_monitor": "降水", - "@precipitation_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 降水" - }, - "temperature_monitor": "氣溫", - "@temperature_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫" - }, - "humidity_monitor": "濕度", - "@humidity_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 濕度" - }, - "pressure_monitor": "氣壓", - "@pressure_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 氣壓" - }, - "wind_direction_and_speed_monitor": "風向/風速", - "@wind_direction_and_speed_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 風向/風速" - }, - "typhoon_monitor": "颱風", - "@typhoon_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 颱風" - }, - "tsunami_info_monitor": "海嘯資訊", - "@tsunami_info_monitor": { - "description": "「地圖」路徑 → 地圖列表 → 海嘯資訊" - }, - "map_legend": "圖例", - "@map_legend": { - "description": "「地圖」路徑 → 地圖列表 → 「圖例」標題" - }, - "unit_dbz": "單位:dBZ", - "@unit_dbz": { - "description": "「地圖」路徑 → 地圖列表 → 「雷達回波」圖例 → 單位:dBZ" - }, - "unit_mm": "單位:毫米 (mm)", - "@unit_mm": { - "description": "「地圖」路徑 → 地圖列表 → 「降水」圖例 → 單位:毫米 (mm)" - }, - "unit_degrees_c": "單位:攝氏度 (°C)", - "@unit_degrees_c": { - "description": "「地圖」路徑 → 地圖列表 → 「氣溫」圖例 → 單位:攝氏度 (°C)" - }, - "unit_relative_humidity": "單位:相對濕度 (%)", - "@unit_relative_humidity": { - "description": "「地圖」路徑 → 地圖列表 → 「濕度」圖例 → 單位:相對濕度 (%)" - }, - "unit_hpa": "單位:百帕 (hPa)", - "@unit_hpa": { - "description": "「地圖」路徑 → 地圖列表 → 「氣壓」圖例 → 單位:百帕 (hPa)" - }, - "history": "歷史", - "@history": { - "description": "「歷史」頁面標題" - }, - "historical_events": "3天內的歷史事件資訊", - "@historical_events": { - "description": "「歷史」路徑 → 「3天內的歷史事件資訊」標題" - }, - "no_historical_events": "沒有歷史事件資訊", - "@no_historical_events": { - "description": "「歷史」路徑 → 沒有歷史事件資訊" - }, - "current_events": "目前的事件資訊", - "@current_events": { - "description": "「首頁」路徑 → 「目前的事件資訊」標題" - }, - "no_events": "目前沒有事件資訊", - "@no_events": { - "description": "「首頁」路徑 → 「目前沒有事件資訊」描述" - }, - "eew_no_x": "第 {serial} 報", - "@eew_no_x": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 第 {serial} 報", - "placeholders": { - "serial": { - "type": "String" - } - } - }, - "lightning": "閃電", - "@lightning": { - "description": "「地圖」路徑 → 地圖列表 → 閃電" - }, - "out_of_service": "服務區域外", - "@out_of_service": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外" - }, - "out_of_service_only_taiwan": "服務區域外,僅在臺灣各地可用", - "@out_of_service_only_taiwan": { - "description": "「設定」路徑 → 「所在地」設定 → 服務區域外,僅在臺灣各地可用" - }, - "unable_notification": "無法取得通知權限", - "@unable_notification": { - "description": "「通知」設定彈窗 → 無法取得通知權限" - }, - "again": "再試一次", - "@again": { - "description": "「通知」設定彈窗 → 再試一次 and " - }, - "unable_location": "無法取得位置權限", - "@unable_location": { - "description": "「所在地」設定彈窗 → 無法取得位置權限" - }, - "cancel": "取消", - "@cancel": { - "description": "「所在地」設定彈窗 → 取消" - }, - "sunny": "晴", - "@sunny": { - "description": "天氣狀況:晴" - }, - "overcast": "陰", - "@overcast": { - "description": "天氣狀況:陰" - }, - "more": "更多", - "@more": { - "description": "「更多」頁面標題" - }, - "more_features": "更多功能列表", - "@more_features": { - "description": "「更多」路徑 → 「更多功能列表」標題" - }, - "me_general": "一般", - "@me_general": { - "description": "「我」路徑 → 一般、「設定」路徑 → 「通知測試」內容 → 通知測試列表" - }, - "me_debug": "除錯", - "@me_debug": { - "description": "「我」路徑 → 除錯" - }, - "official_web": "ExpTech 官網", - "@official_web": { - "description": "「我」路徑 → ExpTech 官網" - }, - "notification_record": "行動通知推播紀錄", - "@notification_record": { - "description": "「我」路徑 → 行動通知推播紀錄" - }, - "advanced_features": "進階功能", - "@advanced_features": { - "description": "「設定」路徑 → 「進階功能」標題" - }, - "advanced_features_title": "調整 DPIP 的進階功能", - "@advanced_features_title": { - "description": "「設定」路徑 → 「進階功能」副描述" - }, - "enable_monitor": "啟用強震監視器", - "@enable_monitor": { - "description": "「設定」路徑 → 「進階功能」標題 → 啟用強震監視器" - }, - "no_tsunami_information": "近期無海嘯資訊", - "@no_tsunami_information": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_warning": "海嘯警報", - "@tsunami_warning": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 近期無海嘯資訊" - }, - "tsunami_number": "{id}號 第{serial}報", - "@tsunami_number": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → {id}號 第{serial}報", - "placeholders": { - "id": { - "type": "String", - "description": "編號" - }, - "serial": { - "type": "String" - } - } - }, - "tsunami_publish": "發布", - "@tsunami_publish": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發布" - }, - "tsunami_renew": "更新", - "@tsunami_renew": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 更新" - }, - "tsunami_relieve": "解除", - "@tsunami_relieve": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 解除" - }, - "estimated_time_wave": "預估海嘯到達時間及波高", - "@estimated_time_wave": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 預估海嘯到達時間及波高" - }, - "observing_tsunamis": "各地觀測到的海嘯", - "@observing_tsunamis": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 各地觀測到的海嘯" - }, - "occurrence_time": "發生時間", - "@occurrence_time": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 發生時間" - }, - "scale": "規模", - "@scale": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 規模" - }, - "depth": "深度", - "@depth": { - "description": "「地圖」路徑 → 地圖列表 → 「海嘯資訊」圖例 → 資訊托盤 → 深度" - }, - "home_safety": "一切平安,無事件發生。", - "@home_safety": { - "description": "「首頁」路徑 → 「一切平安,無事件發生。」描述" - }, - "update_log": "更新日誌", - "@update_log": { - "description": "「我」路徑 → 更新日誌" - }, - "interval_3_days": "3 天", - "@interval_3_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 天" - }, - "interval_2_days": "2 天", - "@interval_2_days": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 2 天" - }, - "interval_24_hours": "24 小時", - "@interval_24_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 24 小時" - }, - "interval_12_hours": "12 小時", - "@interval_12_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 12 小時" - }, - "interval_6_hours": "6 小時", - "@interval_6_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 6 小時" - }, - "interval_3_hours": "3 小時", - "@interval_3_hours": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 3 小時" - }, - "interval_1_hour": "1 小時", - "@interval_1_hour": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 1 小時" - }, - "interval_10_minutes": "10 分鐘", - "@interval_10_minutes": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 10 分鐘" - }, - "interval_now": "今日", - "@interval_now": { - "description": "「地圖」路徑 → 「降水」標題 → 托盤 → 今日" - }, - "welcome_message": "歡迎使用 DPIP", - "@welcome_message": { - "description": "「歡迎」頁面 → 歡迎使用 DPIP" - }, - "disaster_info_platform": "防災資訊平台", - "@disaster_info_platform": { - "description": "「歡迎」頁面 → 防災資訊平台" - }, - "dpip_description": "DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。", - "@dpip_description": { - "description": "「歡迎」頁面 → DPIP 是一款由臺灣本土團隊設計的 App,整合 TREM-Net (臺灣即時地震觀測網) 之資訊,以及中央氣象署資料,提供一個整合、單一且便利的防災資訊應用程式。" - }, - "next_step": "下一步", - "@next_step": { - "description": "「歡迎」頁面 → 下一步" - }, - "who_we_are": "我們是誰?", - "@who_we_are": { - "description": "「歡迎」頁面 → 我們是誰?" - }, - "exptech_studio_description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。", - "@exptech_studio_description": { - "description": "ExpTech Studio 是一群大部分由學生組成,平均年齡未滿 20 歲、人數超過 15 + 的團體。成員來自臺灣北中南、日本、韓國、中國的學生。" - }, - "our_mission": "我們的初衷", - "@our_mission": { - "description": "「歡迎」頁面 → 我們的初衷" - }, - "founding_mission": "成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。", - "@founding_mission": { - "description": "「歡迎」頁面 → 成立初衷是招募一群對電腦及科技有興趣及能力的同學,後來發展至校外,並逐漸形成現在的樣子。" - }, - "notice": "注意事項", - "@notice": { - "description": "「歡迎」頁面 → 注意事項" - }, - "notice_details": "DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。", - "@notice_details": { - "description": "「歡迎」頁面 → DPIP 將傳遞來自 ExpTech 及中央氣象署的各種資訊,使用時請注意以下幾點。" - }, - "official_info": "任何資訊應以中央氣象署發布之內容為準。", - "@official_info": { - "description": "「歡迎」頁面 → 任何資訊應以中央氣象署發布之內容為準。" - }, - "information_reliability": "根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。", - "@information_reliability": { - "description": "「歡迎」頁面 → 根據網路狀態、伺服器狀態、應用程式狀態、上游資料來源狀態等,有收不到資訊的可能性,我們會盡力避免此類情況,但不保證一定不會發生。" - }, - "strong_shake_warning": "強烈搖晃有機率比通知早抵達使用者所在地。", - "@strong_shake_warning": { - "description": "「歡迎」頁面 → 強烈搖晃有機率比通知早抵達使用者所在地。" - }, - "earthquake_alert_warning": "地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。", - "@earthquake_alert_warning": { - "description": "「歡迎」頁面 → 地震速報為快速計算之結果,可能存在較大誤差,應理解並謹慎使用。" - }, - "legal_risks": "任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。", - "@legal_risks": { - "description": "「歡迎」頁面 → 任何不被官方所認可的行為均有可能承擔法律風險,請務必遵守相關規範。" - }, - "permission": "權限", - "@permission": { - "description": "「歡迎」頁面 → 權限" - }, - "privacy_commitment": "我們一直和使用者站在一起,為使用者的隱私而不斷努力。", - "@privacy_commitment": { - "description": "「歡迎」頁面 → 我們一直和使用者站在一起,為使用者的隱私而不斷努力。" - }, - "notification": "通知", - "@notification": { - "description": "「歡迎」頁面 → 通知" - }, - "notification_service_description": "在重大災害發生時以通知來傳遞即時防災資訊", - "@notification_service_description": { - "description": "「歡迎」頁面 → 在重大災害發生時以通知來傳遞即時防災資訊" - }, - "location_based_service": "使用定位來自動更新所在地設定,提供當地的即時防災資訊", - "@location_based_service": { - "description": "「歡迎」頁面 → 使用定位來自動更新所在地設定,提供當地的即時防災資訊" - }, - "data_visualization_storage": "用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片", - "@data_visualization_storage": { - "description": "「歡迎」頁面 → 用於儲存中央氣象署或 ExpTech 提供之數據可視化圖片" - }, - "disagree": "不同意", - "@disagree": { - "description": "強震監視器條款 → 不同意" - }, - "agree": "同意", - "@agree": { - "description": "強震監視器條款 → 同意" - }, - "trem_service_description": "在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。", - "@trem_service_description": { - "description": "在 DPIP 中可以查看來自 ExpTech 旗下 TREM 之強震監視器服務,請詳細閱讀以下條件,並選擇是否啟用。" - }, - "real_time_magnitude_warning": "顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。", - "@real_time_magnitude_warning": { - "description": "顯示的即時震度不是中央氣象署所提供之資料,因此可能與中央氣象署觀測到的結果不一致,應以中央氣象署公布之資訊為主。" - }, - "trem_station_warning": "強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。", - "@trem_station_warning": { - "description": "強震監視器使用之測站為 ExpTech 所有,不歸中央氣象署管理,請不要向中央氣象署傳遞故障或意見,會造成他們的困擾。" - }, - "trem_monitor_description": "強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。", - "@trem_monitor_description": { - "description": "強震監視器是由 TREM(臺灣即時地震監測)觀測到全臺現在的震動,做為即時震度顯示的功能,地震發生當下可以透過站點顏色變化,觀察地震波傳播情形。" - }, - "station_noise_warning": "由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。", - "@station_noise_warning": { - "description": "由於日常雜訊(汽車、工廠、施工等)影響,平時站點可能也會有顏色變化。另外,由於是即時資料,當下無法判斷是否是故障,所以也有可能因為站點故障而改變顏色。" - }, - "trem_net_deployment": "2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。", - "@trem_net_deployment": { - "description": "2022 年 6 月初開始於全臺各地部署站點,TREM-Net(TREM 地震觀測網)由兩個觀測網組成,分別為 SE-Net(強震觀測網「加速度儀」)及 MS-Net(微震觀測網「速度儀」),共同紀錄地震時的各項數據。" - }, - "discover_new_version": "發現新版本", - "@discover_new_version": { - "description": "「發現新版本」頁面 → 發現新版本" - }, - "update_to_latest_version": "更新至最新版本以獲得最佳體驗", - "@update_to_latest_version": { - "description": "「發現新版本」頁面 → 更新至最新版本以獲得最佳體驗" - }, - "current_version": "目前版本", - "@current_version": { - "description": "「發現新版本」頁面 → 目前版本" - }, - "latest_version": "最新版本", - "@latest_version": { - "description": "「發現新版本」頁面 → 最新版本" - }, - "update_now": "立即更新", - "@update_now": { - "description": "「發現新版本」頁面 → 立即更新" - }, - "skip_for_now": "暫時略過", - "@skip_for_now": { - "description": "「發現新版本」頁面 → 暫時略過" - }, - "update_complete": "更新完成", - "@update_complete": { - "description": "「發現新版本」頁面 → 更新完成" - }, - "update_complete_prompt": "DPIP 更新完成,要前往查看更新日誌嗎?", - "@update_complete_prompt": { - "description": "「發現新版本」頁面 → DPIP 更新完成,要前往查看更新日誌嗎?" - }, - "remind_later": "稍後再說", - "@remind_later": { - "description": "「發現新版本」頁面 → 稍後再說" - }, - "go_to_view": "前往查看", - "@go_to_view": { - "description": "「發現新版本」頁面 → 前往查看" - }, - "announcement": "公告", - "@announcement": { - "description": "「我」路徑 → 公告" - }, - "new_announcement_prompt": "有新的公告,要前往查看嗎?", - "@new_announcement_prompt": { - "description": "「新公告」頁面 → 有新的公告,要前往查看嗎?" - }, - "no_announcements": "目前沒有公告", - "@no_announcements": { - "description": "「公告」標題 → 目前沒有公告" - }, - "contributor": "貢獻者", - "@contributor": { - "description": "「我」路徑 → 貢獻者" - }, - "unable_to_load_changelog": "無法載入更新日誌,請稍後再試。", - "@unable_to_load_changelog": { - "description": "「我」路徑 →「更新日誌」標題 → 無法載入更新日誌,請稍後再試。" - }, - "no_changelog": "目前沒有更新日誌", - "@no_changelog": { - "description": "「我」路徑 → 「更新日誌」標題 → 當前沒有任何更新日誌" - }, - "announcement_details": "公告詳情", - "@announcement_details": { - "description": "「我」路徑 → 「公告」標題 → 查看公告的具體內容" - }, - "version_details": "版本詳情", - "@version_details": { - "description": "「我」路徑 → 「更新日誌」標題 → 版本詳情" - }, - "unable_to_obtain_permission": "無法取得權限", - "@unable_to_obtain_permission": { - "description": "當無法獲取應用程式所需的權限時顯示的消息 → 無法取得權限" - }, - "error_saving_image": "儲存圖片時發生錯誤", - "@error_saving_image": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤" - }, - "confirm": "確定", - "@confirm": { - "description": "用於確認操作的按鈕文字 → 儲存圖片時發生錯誤" - }, - "no_search_results": "無搜尋結果", - "@no_search_results": { - "description": "當搜尋無結果時顯示的訊息 → 儲存圖片時發生錯誤" - }, - "always_allow": "一律允許", - "@always_allow": { - "description": "「存取權限彈窗」 → 一律允許" - }, - "always": "永遠", - "@always": { - "description": "「存取權限彈窗」 → 永遠" - }, - "auto_start_permission_info": "為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。", - "@auto_start_permission_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "auto_start_permission_experience": "為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。", - "@auto_start_permission_experience": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「自啟動權限」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "auto_start_permission": "自啟動權限", - "@auto_start_permission": { - "description": "「存取權限彈窗」 → 自啟動權限" - }, - "auto_location_experience_info": "為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。", - "@auto_location_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的自動定位體驗,您需要給予「無限制」以便讓 DPIP 在背景自動設定所在地資訊。" - }, - "unlimited_permission_experience_info": "為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。", - "@unlimited_permission_experience_info": { - "description": "「存取權限彈窗」 → 為了獲得更好的 DPIP 體驗,您需要給予「無限制」以便讓 DPIP 在背景有正常接收警訊通知。" - }, - "power_saving_strategy": "省電策略", - "@power_saving_strategy": { - "description": "「存取權限彈窗」 → 省電策略" - }, - "notification_permission_denied": "通知功能已被拒絕,請移至設定允許權限。", - "@notification_permission_denied": { - "description": "「存取權限彈窗」 → 通知功能已被拒絕,請移至設定允許權限。" - }, - "autoStart_permission_denied": "自啟動權限已被拒絕,請移至設定允許權限。", - "@autoStart_permission_denied": { - "description": "「存取權限彈窗」 → 自啟動權限已被拒絕,請移至設定允許權限。" - }, - "batteryOptimization_permission_denied": "省電策略已被拒絕,請移至設定允許權限。", - "@batteryOptimization_permission_denied": { - "description": "「存取權限彈窗」 → 省電策略已被拒絕,請移至設定允許權限。" - }, - "permission_request": "權限請求", - "@permission_request": { - "description": "「存取權限彈窗」 → 權限請求" - }, - "manual_permission_enablement": "需要使用者手動到設定開啟相關權限。", - "@manual_permission_enablement": { - "description": "「存取權限彈窗」 → 需要使用者手動到設定開啟相關權限。" - }, - "location_not_set": "尚未設定所在地", - "@location_not_set": { - "description": "「尚未設定所在地彈窗」 → 尚未設定所在地" - }, - "location_setting_required": "DPIP 需要設定所在地才能正常運作。點擊「前往設定」設定所在地後再試一次。", - "@location_setting_required": { - "description": "提示用戶需要設定所在地才能正常運作的訊息" - }, - "go_to_settings": "前往設定", - "@go_to_settings": { - "description": "引導用戶前往設定的選項" - }, - "app_logs": "App 日誌", - "@app_logs": { - "description": "「我」路徑 → App 日誌" - }, - "copy_fcm_token_error": "複製 FCM Token 時發生錯誤", - "@copy_fcm_token_error": { - "description": "「我」路徑 → 複製 FCM Token 時發生錯誤" - }, - "estimated_intensity_legend": "預估震度圖例", - "@estimated_intensity_legend": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 描述預估震度的圖例" - }, - "only_used_during_earthquake_alerts": "僅用於地震速報時", - "@only_used_during_earthquake_alerts": { - "description": "「地圖」路徑 → 強震監視器 → 「!」圖例 → 此項目僅在地震速報時使用" - }, - "intensity": "{count, select, 5{5弱} 6{5強} 7{6弱} 8{6強} 9{7級} other{{count}級}}", - "@intensity": { - "description": "震度", - "placeholders": { - "count": { - "type": "String" - } - } - }, - "lightning_1_5": "5 分鐘內對地閃電", - "@lightning_1_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的對地閃電" - }, - "lightning_1_10": "10 分鐘內對地閃電", - "@lightning_1_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的對地閃電" - }, - "lightning_1_30": "30 分鐘內對地閃電", - "@lightning_1_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的對地閃電" - }, - "lightning_1_60": "60 分鐘內對地閃電", - "@lightning_1_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的對地閃電" - }, - "lightning_0_5": "5 分鐘內雲間閃電", - "@lightning_0_5": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 5 分鐘內發生的雲間閃電" - }, - "lightning_0_10": "10 分鐘內雲間閃電", - "@lightning_0_10": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 10 分鐘內發生的雲間閃電" - }, - "lightning_0_30": "30 分鐘內雲間閃電", - "@lightning_0_30": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 30 分鐘內發生的雲間閃電" - }, - "lightning_0_60": "60 分鐘內雲間閃電", - "@lightning_0_60": { - "description": "「地圖」路徑 → 地圖列表 → 閃電 → 「!」圖例 → 60 分鐘內發生的雲間閃電" - }, - "abnormal": "異常", - "@abnormal": { - "description": "狀態:異常" - }, - "network_or_server_error": "網路連線或伺服器異常。", - "@network_or_server_error": { - "description": "網路連線或伺服器異常。" - }, - "retry": "重試", - "@retry": { - "description": "重試" - }, - "photo_media_permission_request": "請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。", - "@photo_media_permission_request": { - "description": "「更多」路徑 → 地震報告 → 詳細地震報告 → 地震報告請您到應用程式設定中找到並允許「相片和媒體」權限後再試一次。" - }, - "no_notification_history": "沒有通知紀錄", - "@no_notification_history": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 沒有通知紀錄" - }, - "emergency": "緊急", - "@emergency": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急" - }, - "notification_details": "通知詳細資訊", - "@notification_details": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知詳細資訊" - }, - "notification_area": "通知發送區域", - "@notification_area": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 通知發送區域" - }, - "emergency_notification": "緊急通知", - "@emergency_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 緊急通知" - }, - "general_notification": "一般通知", - "@general_notification": { - "description": "「我」路徑 →「行動通知推播紀錄」標題 → 一般通知" - }, - "please_allow_notification_permission": "請您到應用程式設定中找到並允許「通知」權限後再試一次。", - "@please_allow_notification_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「通知」權限後再試一次。" - }, - "please_allow_location_permission": "請您到應用程式設定中找到並允許「位置」權限後再試一次。", - "@please_allow_location_permission": { - "description": "「設定」路徑 → 請您到應用程式設定中找到並允許「位置」權限後再試一次。" - }, - "no_data_available": "沒有可用的資料", - "@no_data_available": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 沒有可用的資料" - }, - "server_status_overview": "此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。", - "@server_status_overview": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 此頁面呈現伺服器各時段狀態概覽。原始資料每5秒更新一次,此處顯示精簡版本以最佳化網路用量。請注意,此資訊僅供參考,實際狀況應以公告為準。" - }, - "all_normal": "全部正常", - "@all_normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部正常" - }, - "all_abnormal": "全部異常", - "@all_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:全部異常" - }, - "partially_abnormal": "部分異常", - "@partially_abnormal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 伺服器狀態:部分異常" - }, - "normal": "正常", - "@normal": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:正常" - }, - "unstable": "不穩定", - "@unstable": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:不穩定" - }, - "no_data": "無資料", - "@no_data": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 狀態:無資料" - }, - "automatic_foreground_positioning": "前景自動定位", - "@automatic_foreground_positioning": { - "description": "前景自動定位" - }, - "south_latitude": "南緯 {lat_abs} 度", - "@south_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 南緯 {lat_abs} 度", - "placeholders": { - "lat_abs": { - "type": "String" - } - } - }, - "north_latitude": "北緯 {lat} 度", - "@north_latitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 北緯 {lat} 度", - "placeholders": { - "lat": { - "type": "String" - } - } - }, - "west_longitude": "西經 {lon_abs} 度", - "@west_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 西經 {lon_abs} 度", - "placeholders": { - "lon_abs": { - "type": "String" - } - } - }, - "east_longitude": "東經 {lon} 度", - "@east_longitude": { - "description": "「地圖」路徑 → 「海嘯資訊」標題 → 東經 {lon} 度", - "placeholders": { - "lon": { - "type": "String" - } - } - }, - "delay": "延遲: {serviceStatus_count} ms", - "@delay": { - "description": "「我」路徑 → 「伺服器狀態」標題 → 資訊內容 → 延遲: {serviceStatus_count} ms", - "placeholders": { - "serviceStatus_count": { - "type": "String" - } - } - }, - "me_developer": "開發者想說的話", - "@me_developer": { - "description": "「我」路徑 → 「開發者想說的話」標題" - }, - "me_about": "關於", - "@me_about": { - "description": "「我」路徑 → 關於" - }, - "alarm_area": "警報區域", - "@alarm_area": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 警報區域" - }, - "estimated_intensity": "預估最大震度", - "@estimated_intensity": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 預估最大震度" - }, - "time_earthquake": "發震", - "@time_earthquake": { - "description": "「地圖」路徑 → 強震監視器 → 資訊托盤 → 發震" - }, - "no_earthquake_monitor": "未啟用強震監視器", - "@no_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 未啟用強震監視器" - }, - "settings_earthquake_monitor": "請至設定進階功能中開啟強震監視器。", - "@settings_earthquake_monitor": { - "description": "「地圖」路徑 → 強震監視器 → 提示資訊 → 請至設定進階功能中開啟強震監視器。" - }, - "view_prompt_information": "點擊查看提示資訊", - "@view_prompt_information": { - "description": "「地圖」路徑 → 強震監視器 → 點擊查看提示資訊" - }, - "highest": "最高", - "@highest": { - "description": "「首頁」路徑 → 「最高」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最高" - }, - "lowest": "最低", - "@lowest": { - "description": "「首頁」路徑 → 「最低」描述、「排行榜」頁面 → 氣溫資訊頁面 → 最低" - }, - "not_enabled": " (未啟用)", - "@not_enabled": { - "description": "「設定」路徑 → 「通知測試」內容 →「 (未啟用)」副標題 " - }, - "introduction": "簡介", - "@introduction": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 簡介" - }, - "first_gratitude": "首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。", - "@first_gratitude": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先感謝所有下載這個軟體的使用者,整個開發團隊在此獻上最誠摯的謝意。" - }, - "dpip_goal": "DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。", - "@dpip_goal": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 是一個以整合所有防災資訊為目標的軟體,希望能成為民眾生活中不可或缺的一部分。儘管目前完成度不高且困難重重,但我們仍會持續朝這個目標前進。" - }, - "development_investment": "在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。", - "@development_investment": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 在開發軟體時,我們投入了大量的金錢、時間與精力,在人事成本、設備費用、雲端服務、網路費用等項目上,花費超過50萬新台幣。為此,我們希望獲得使用者的支持,在不依賴其他第三方公司的前提下,繼續維持營運。" - }, - "profit_model": "營利模式", - "@profit_model": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利模式" - }, - "profit_discussion": "為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。", - "@profit_discussion": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為了維持 App 的開發,團隊內部進行了多次激烈討論,思考如何才能營利?我們試圖在眾多方案中,找出一個適合的營利模式。我們發現,大多數同類型軟體採用植入廣告的方式來達到營利目的,這使得我們一度考慮採用該方式作為營利的方法。" - }, - "profit_difficulty": "營利真的太難了", - "@profit_difficulty": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 營利真的太難了" - }, - "user_payment_survey": "我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。", - "@user_payment_survey": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 我們調查了一般民眾的付費意願,發現大部分人普遍防災意識不足,更不會花錢在這件事情上。後台的數據能側面證實這個說法,據統計,熱心贊助的民眾大約是整體使用者的10萬分之1,這使得植入廣告似乎成為了最好的解決方法。" - }, - "why_no_ads": "為什麼不採用廣告?", - "@why_no_ads": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 為什麼不採用廣告?" - }, - "no_ads_reason": "當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。", - "@no_ads_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 當災害發生時,大家一定不會想要看廣告吧?這是我們不植入廣告的第一個理由。防災導向的軟體,快速正確地傳遞防災資訊是首要任務。如果因為廣告而導致無法正確掌握防災資訊,這反而和我們的理念相違背。況且,災害發生時通常通訊品質不佳,還要額外浪費網路流量在載入廣告,這件事太令人沮喪了。" - }, - "charge_public": "對大眾收費?", - "@charge_public": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 對大眾收費?" - }, - "no_fee_reason": "如果植入廣告行不通,那對大眾收費呢?變成付費軟體?", - "@no_fee_reason": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如果植入廣告行不通,那對大眾收費呢?變成付費軟體?" - }, - "public_charge_consideration": "首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。", - "@public_charge_consideration": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 首先,作為防災軟體,我們希望盡可能地將防災資訊傳遞給越多人越好。而且,或許真正需要的人沒辦法再多出額外的經費承擔這項支出,我們希望幫助更多的人。其次,作為開發人員,我們希望軟體可以有很多人使用,收費會直接導致大家使用意願降低。" - }, - "how_to_profit": "如何營利?", - "@how_to_profit": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 如何營利?" - }, - "summary": "總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。", - "@summary": { - "description": "「我」路徑 → 「開發者想說的話」內容 → 總結上述,我們希望培養出對防災有興趣的人、重視防災的人,支持我們的軟體開發,一起往前發展。" - }, - "developer_message": "DPIP 開發者的話", - "@developer_message": { - "description": "「我」路徑 → 「開發者想說的話」內容 → DPIP 開發者的話" - }, - "error_fetching_announcement": "獲取公告時發生錯誤:", - "@error_fetching_announcement": { - "description": "「我」路徑 →「公告」標題 → 獲取公告時發生錯誤:" - }, - "invalid_operation": "無效操作", - "@invalid_operation": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 無效操作" - }, - "operation_interval_too_short": "操作間隔過短,請稍後再嘗試。", - "@operation_interval_too_short": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 操作間隔過短,請稍後再嘗試。" - }, - "got_it": "知道了", - "@got_it": { - "description": "「通知測試」 → 「操作時間過短」彈窗 → 知道了" - }, - "error_fcm_token": "錯誤: 無法取得 FCM Token", - "@error_fcm_token": { - "description": "錯誤:無法取得 FCM Token" - }, - "error_fetching_notifications": "獲取通知紀錄時發生錯誤", - "@error_fetching_notifications": { - "description": "「我」路徑 →「行動通知推播紀錄」→ 獲取通知紀錄時發生錯誤" - }, - "auto_location_permission_required": "自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。", - "@auto_location_permission_required": { - "description": "「通知權限」彈窗 → 自動定位功能需要您允許 DPIP 使用通知權限才能正常運作。" - }, - "location_permission_needed": "自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。", - "@location_permission_needed": { - "description": "「位置權限」彈窗 → 自動定位功能需要您允許 DPIP 使用位置權限才能正常運作。" - }, - "location_permission": "位置權限", - "@location_permission": { - "description": "「位置權限」彈窗 → 用於提示用戶授予位置權限" - }, - "improve_auto_location_experience": "為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "@improve_auto_location_experience": { - "description": "「位置權限」彈窗 → 為了獲得更好的自動定位體驗,您需要將位置權限提升至「{permissionType}」以便讓 DPIP 在背景自動設定所在地資訊。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "auto_location_permission_upgrade_needed": "自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "@auto_location_permission_upgrade_needed": { - "description": "「通知權限」彈窗 → 自動定位功能需要將位置權限提升至「{permissionType}」以在背景使用。", - "placeholders": { - "permissionType": { - "type": "String" - } - } - }, - "error_prefix": "錯誤:", - "@error_prefix": { - "description": "錯誤:前綴" - }, - "home_precipitation": "降水量", - "@home_precipitation": { - "description": "「首頁」頁面 → 降水量" - }, - "history_nationwide": "全國", - "@history_nationwide": { - "description": "「歷史」頁面 → 全國" - }, - "me_welcome": "歡迎頁面", - "@me_welcome": { - "description": "「我」頁面 → 「歡迎頁面」按鈕" - }, - "donate_h2": "幫助我們維護伺服器的穩定和長久發展", - "@donate_h2": { - "description": "「我」頁面 →「幫助我們維護伺服器的穩定和長久發展」描述" - }, - "max_earthquake_intensity": "最大震度", - "@max_earthquake_intensity": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 最大震度" - }, - "report_all": "全部", - "@report_all": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」→ 全部" - }, - "report_filter": "篩選器", - "@report_filter": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」" - }, - "report_filter_reset": "重置", - "@report_filter_reset": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 重置" - }, - "report_filter_apply": "套用", - "@report_filter_apply": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 套用" - }, - "report_end": "到底了", - "@report_end": { - "description": "「更多」路徑 → 地震報告 → 使用「篩選器」 → 到底了" - }, - "history_send_time": "發送時間", - "@history_send_time": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 發送時間" - }, - "history_valid_until": "有效至", - "@history_valid_until": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 有效至" - }, - "history_affected_area": "影響區域", - "@history_affected_area": { - "description": "「歷史」路徑 → 歷史事件資訊列表 → 彈窗事件 → 影響區域" - }, - "sound_eew_alert_major": "緊急地震速報(重大)", - "@sound_eew_alert_major": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(重大)" - }, - "sound_eew_minor": "緊急地震速報(一般)", - "@sound_eew_minor": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(一般)" - }, - "sound_eew_silent": "緊急地震速報(無聲)", - "@sound_eew_silent": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 緊急地震速報(無聲)" - }, - "sound_eew_silent_h2": "最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上", - "@sound_eew_silent_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 「緊急地震速報(無聲)」描述 → 最大震度 5 弱以上 且\n所在地(鄉鎮)預估震度 1 以上" - }, - "sound_earthquake_eew_major": "地震速報(重大)", - "@sound_earthquake_eew_major": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 地震速報(重大)" - }, - "sound_earthquake_eew_major_h2": "所在地(鄉鎮)預估震度 4 以上", - "@sound_earthquake_eew_major_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 「地震速報(重大)」描述 → 所在地(鄉鎮)預估震度 4 以上" - }, - "sound_earthquake_eew_minor": "地震速報(一般)", - "@sound_earthquake_eew_minor": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 地震速報(一般)" - }, - "sound_earthquake_eew_minor_h2": "所在地(鄉鎮)預估震度 2 以上", - "@sound_earthquake_eew_minor_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 2 以上" - }, - "sound_earthquake_eew_silent": "地震速報(無聲)", - "@sound_earthquake_eew_silent": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 地震速報(無聲)" - }, - "sound_earthquake_eew_silent_h2": "所在地(鄉鎮)預估震度 1 以上", - "@sound_earthquake_eew_silent_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「緊急地震速報」標題 → 「地震速報(一般)」描述 → 所在地(鄉鎮)預估震度 1 以上" - }, - "sound_int_report_minor": "震度速報(一般)", - "@sound_int_report_minor": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 震度速報(一般)" - }, - "sound_int_report_minor_h2": "所在地(鄉鎮)實測震度 3 以上", - "@sound_int_report_minor_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 「震度速報(一般)」描述 → 所在地(鄉鎮)實測震度 3 以上" - }, - "sound_int_report_silent": "震度速報(無聲通知)", - "@sound_int_report_silent": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 震度速報(無聲通知)" - }, - "sound_int_report_silent_h2": "所在地(鄉鎮)實測震度 1 以上", - "@sound_int_report_silent_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 「震度速報(無聲通知)」描述 → 所在地(鄉鎮)實測震度 1 以上。" - }, - "sound_monitor_minor": "強震監視器(一般)", - "@sound_monitor_minor": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 強震監視器(一般)" - }, - "sound_report_minor": "地震報告(一般)", - "@sound_report_minor": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 地震報告(一般)" - }, - "sound_report_silent": "地震報告(無聲通知)", - "@sound_report_silent": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 地震報告(無聲通知)" - }, - "sound_report_silent_h2": "所在地(縣市)實測震度 1 以上", - "@sound_report_silent_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「地震資訊」標題 → 「地震報告(無聲通知)」描述 → 所在地(縣市)實測震度 1 以上" - }, - "sound_weather_warning": "氣象警報", - "@sound_weather_warning": { - "description": "「我」路徑 → 「音效測試」內容 → 「氣象警報」標題" - }, - "sound_rain_instant": "雷雨即時訊息", - "@sound_rain_instant": { - "description": "「我」路徑 → 「音效測試」內容 → 「雷雨即時訊息」標題" - }, - "sound_weather_alert": "天氣警特報", - "@sound_weather_alert": { - "description": "「我」路徑 → 「音效測試」內容 → 「天氣警特報」標題" - }, - "sound_rain_minor_h2": "所在地(鄉鎮)發布雷雨即時訊息或\n山區暴雨時", - "@sound_rain_minor_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「氣象警報」標題 → 「雷雨即時訊息(一般)」描述 → 所在地(鄉鎮)發布雷雨即時訊息\n或山區暴雨時" - }, - "sound_weather_major_h2": "所在地(鄉鎮)發布紅色燈號之\n天氣警特報", - "@sound_weather_major_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「氣象警報」標題 → 「天氣警特報(重大)」描述 → 所在地(鄉鎮)發布紅色燈號之天氣警特報" - }, - "sound_weather_minor_h2": "所在地(鄉鎮)發布上述除外燈號之\n天氣警特報", - "@sound_weather_minor_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「氣象警報」標題 → 「天氣警特報(一般)」描述 → 所在地(鄉鎮)發布上述除外燈號之天氣警特報" - }, - "sound_disaster": "災害資訊", - "@sound_disaster": { - "description": "「我」路徑 → 「音效測試」內容 → 「災害資訊」標題" - }, - "sound_evacuation": "避難資訊", - "@sound_evacuation": { - "description": "「我」路徑 → 「音效測試」內容 → 「避難資訊」標題" - }, - "sound_evacuation_major_h2": "所在地(鄉鎮)發布避難警訊時", - "@sound_evacuation_major_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「災害資訊」標題 → 「避難資訊(重大)」描述 → 所在地(鄉鎮)發布避難警訊時" - }, - "sound_evacuation_minor_h2": "所在地(鄉鎮)發布避難資訊時", - "@sound_evacuation_minor_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「災害資訊」標題 → 「避難資訊(一般)」描述 → 所在地(鄉鎮)發布避難資訊時" - }, - "sound_tsunami_silent": "太平洋海嘯消息(無聲通知)", - "@sound_tsunami_silent": { - "description": "「我」路徑 → 「音效測試」內容 → 「海嘯警報」標題 → 太平洋海嘯消息(無聲通知)" - }, - "sound_tsunami_silent_h2": "太平洋海嘯消息發布時", - "@sound_tsunami_silent_h2": { - "description": "「我」路徑 → 「音效測試」內容 → 「海嘯警報」標題 → 「太平洋海嘯消息(無聲通知)」描述 → 太平洋海嘯消息發布時" - }, - "sound_other_notifications": "其他通知", - "@sound_other_notifications": { - "description": "「我」路徑 → 「音效測試」內容 → 「其他通知」標題 " - }, - "sound_major": "重大", - "@sound_major": { - "description": "「我」路徑 → 「音效測試」內容 → 重大" - }, - "sunny_with_haze": "晴有霾", - "@sunny_with_haze": { - "description": "天氣狀況:晴天伴有霾" - }, - "sunny_with_mist": "晴有靄", - "@sunny_with_mist": { - "description": "天氣狀況:晴天伴有靄" - }, - "sunny_with_lightning": "晴有閃電", - "@sunny_with_lightning": { - "description": "天氣狀況:晴天伴有閃電" - }, - "sunny_with_fog": "晴有霧", - "@sunny_with_fog": { - "description": "天氣狀況:晴天伴有霧" - }, - "sunny_with_rain": "晴有雨", - "@sunny_with_rain": { - "description": "天氣狀況:晴天伴有雨" - }, - "sunny_with_sleet": "晴有雨雪", - "@sunny_with_sleet": { - "description": "天氣狀況:晴天伴有雨夾雪" - }, - "sunny_with_heavy_snow": "晴有大雪", - "@sunny_with_heavy_snow": { - "description": "天氣狀況:晴天伴有大雪" - }, - "sunny_with_snow_pellets": "晴有雪珠", - "@sunny_with_snow_pellets": { - "description": "天氣狀況:晴天伴有雪珠" - }, - "sunny_with_ice_pellets": "晴有冰珠", - "@sunny_with_ice_pellets": { - "description": "天氣狀況:晴天伴有冰珠" - }, - "sunny_with_snow_showers": "晴有陣雪", - "@sunny_with_snow_showers": { - "description": "天氣狀況:晴天伴有陣雪" - }, - "sunny_with_sleet_showers": "晴陣雨雪", - "@sunny_with_sleet_showers": { - "description": "天氣狀況:晴天伴有陣雨夾雪" - }, - "sunny_with_hail": "晴有雹", - "@sunny_with_hail": { - "description": "天氣狀況:晴天伴有冰雹" - }, - "sunny_with_thunderstorm": "晴有雷雨", - "@sunny_with_thunderstorm": { - "description": "天氣狀況:晴天伴有雷雨" - }, - "sunny_with_thundersnow": "晴有雷雪", - "@sunny_with_thundersnow": { - "description": "天氣狀況:晴天伴有雷雪" - }, - "sunny_with_thunderhail": "晴有雷雹", - "@sunny_with_thunderhail": { - "description": "天氣狀況:晴天伴有雷雹" - }, - "sunny_with_severe_thunderstorm": "晴大雷雨", - "@sunny_with_severe_thunderstorm": { - "description": "天氣狀況:晴天伴有強雷雨" - }, - "sunny_with_severe_thunderhail": "晴大雷雹", - "@sunny_with_severe_thunderhail": { - "description": "天氣狀況:晴天伴有強雷雹" - }, - "sunny_with_thunder": "晴天伴有雷", - "@sunny_with_thunder": { - "description": "天氣狀況:晴天伴有雷" - }, - "partly__cloudy": "多雲", - "@partly__cloudy": { - "description": "天氣狀況:多雲" - }, - "partly_cloudy_with_haze": "多雲有霾", - "@partly_cloudy_with_haze": { - "description": "天氣狀況:多雲伴有霾" - }, - "partly_cloudy_with_mist": "多雲有靄", - "@partly_cloudy_with_mist": { - "description": "天氣狀況:多雲伴有靄" - }, - "partly_cloudy_with_lightning": "多雲有閃電", - "@partly_cloudy_with_lightning": { - "description": "天氣狀況:多雲伴有閃電" - }, - "partly_cloudy_with_fog": "多雲有霧", - "@partly_cloudy_with_fog": { - "description": "天氣狀況:多雲伴有霧" - }, - "partly_cloudy_with_rain": "多雲有雨", - "@partly_cloudy_with_rain": { - "description": "天氣狀況:多雲伴有雨" - }, - "partly_cloudy_with_sleet": "多雲有雨雪", - "@partly_cloudy_with_sleet": { - "description": "天氣狀況:多雲伴有雨夾雪" - }, - "partly_cloudy_with_heavy_snow": "多雲有大雪", - "@partly_cloudy_with_heavy_snow": { - "description": "天氣狀況:多雲伴有大雪" - }, - "partly_cloudy_with_snow_pellets": "多雲有雪珠", - "@partly_cloudy_with_snow_pellets": { - "description": "天氣狀況:多雲伴有雪珠" - }, - "partly_cloudy_with_ice_pellets": "多雲有冰珠", - "@partly_cloudy_with_ice_pellets": { - "description": "天氣狀況:多雲伴有冰珠" - }, - "partly_cloudy_with_snow_showers": "多雲有陣雪", - "@partly_cloudy_with_snow_showers": { - "description": "天氣狀況:多雲伴有陣雪" - }, - "partly_cloudy_with_sleet_showers": "多雲陣雨雪", - "@partly_cloudy_with_sleet_showers": { - "description": "天氣狀況:多雲伴有陣雨夾雪" - }, - "partly_cloudy_with_hail": "多雲有雹", - "@partly_cloudy_with_hail": { - "description": "天氣狀況:多雲伴有冰雹" - }, - "partly_cloudy_with_thunderstorm": "多雲有雷雨", - "@partly_cloudy_with_thunderstorm": { - "description": "天氣狀況:多雲伴有雷雨" - }, - "partly_cloudy_with_thundersnow": "多雲有雷雪", - "@partly_cloudy_with_thundersnow": { - "description": "天氣狀況:多雲伴有雷雪" - }, - "partly_cloudy_with_thunderhail": "多雲有雷雹", - "@partly_cloudy_with_thunderhail": { - "description": "天氣狀況:多雲伴有雷雹" - }, - "partly_cloudy_with_severe_thunderstorm": "多雲大雷雨", - "@partly_cloudy_with_severe_thunderstorm": { - "description": "天氣狀況:多雲伴有強雷雨" - }, - "partly_cloudy_with_severe_thunderhail": "多雲大雷雹", - "@partly_cloudy_with_severe_thunderhail": { - "description": "天氣狀況:多雲伴有強雷雹" - }, - "partly_cloudy_with_thunder": "多雲伴有雷", - "@partly_cloudy_with_thunder": { - "description": "天氣狀況:多雲伴有雷" - }, - "overcast_with_haze": "陰有霾", - "@overcast_with_haze": { - "description": "天氣狀況:陰天伴有霾" - }, - "overcast_with_mist": "陰有靄", - "@overcast_with_mist": { - "description": "天氣狀況:陰天伴有靄" - }, - "overcast_with_lightning": "陰有閃電", - "@overcast_with_lightning": { - "description": "天氣狀況:陰天伴有閃電" - }, - "overcast_with_fog": "陰有霧", - "@overcast_with_fog": { - "description": "天氣狀況:陰天伴有霧" - }, - "overcast_with_rain": "陰有雨", - "@overcast_with_rain": { - "description": "天氣狀況:陰天伴有雨" - }, - "overcast_with_sleet": "陰有雨雪", - "@overcast_with_sleet": { - "description": "天氣狀況:陰天伴有雨夾雪" - }, - "overcast_with_heavy_snow": "陰有大雪", - "@overcast_with_heavy_snow": { - "description": "天氣狀況:陰天伴有大雪" - }, - "overcast_with_snow_pellets": "陰有雪珠", - "@overcast_with_snow_pellets": { - "description": "天氣狀況:陰天伴有雪珠" - }, - "overcast_with_ice_pellets": "陰有冰珠", - "@overcast_with_ice_pellets": { - "description": "天氣狀況:陰天伴有冰珠" - }, - "overcast_with_snow_showers": "陰有陣雪", - "@overcast_with_snow_showers": { - "description": "天氣狀況:陰天伴有陣雪" - }, - "overcast_with_sleet_showers": "陰陣雨雪", - "@overcast_with_sleet_showers": { - "description": "天氣狀況:陰天伴有陣雨夾雪" - }, - "overcast_with_hail": "陰有雹", - "@overcast_with_hail": { - "description": "天氣狀況:陰天伴有冰雹" - }, - "overcast_with_thunderstorm": "陰有雷雨", - "@overcast_with_thunderstorm": { - "description": "天氣狀況:陰天伴有雷雨" - }, - "overcast_with_thundersnow": "陰有雷雪", - "@overcast_with_thundersnow": { - "description": "天氣狀況:陰天伴有雷雪" - }, - "overcast_with_thunderhail": "陰有雷雹", - "@overcast_with_thunderhail": { - "description": "天氣狀況:陰天伴有雷雹" - }, - "overcast_with_severe_thunderstorm": "陰大雷雨", - "@overcast_with_severe_thunderstorm": { - "description": "天氣狀況:陰天伴有強雷雨" - }, - "overcast_with_severe_thunderhail": "陰大雷雹", - "@overcast_with_severe_thunderhail": { - "description": "天氣狀況:陰天伴有強雷雹" - }, - "overcast_with_thunder": "陰天伴有雷", - "@overcast_with_thunder": { - "description": "天氣狀況:陰天伴有雷" - }, - "get_weather_abnormal": "取得天氣異常", - "@get_weather_abnormal": { - "description": "取得天氣異常" - }, - "map_average": "平均", - "@map_average": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 平均" - }, - "radar_synthetic_echo": "雷達合成回波", - "@radar_synthetic_echo": { - "description": "「天氣警特報」地圖解釋 → 雷達合成回波" - }, - "completed": "已結束", - "@completed": { - "description": "「天氣警特報」狀態 → 已結束" - }, - "active": "生效中", - "@active": { - "description": "「天氣警特報」狀態 → 生效中" - }, - "save_image_permission": "儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。", - "@save_image_permission": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片需要您允許 DPIP 使用相片和媒體權限才能正常運作。" - }, - "save_image_error": "儲存圖片時發生錯誤:", - "@save_image_error": { - "description": "當儲存圖片失敗時顯示的錯誤消息 → 儲存圖片時發生錯誤:" - }, - "error_occurred": "發生錯誤:", - "@error_occurred": { - "description": "Weather Status: An error occurred:" - }, - "history_final": "(最終)", - "@history_final": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → (最終)" - }, - "level_1": "1級", - "@level_1": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 1級" - }, - "level_2": "2級", - "@level_2": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 2級" - }, - "level_3": "3級", - "@level_3": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 3級" - }, - "level_4": "4級", - "@level_4": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 4級" - }, - "level_7": "7級", - "@level_7": { - "description": "「更多」路徑 → 地震報告 → 「篩選器」圖例 → 彈出資訊 → 7級" - }, - "home_click_settings": "點擊設定所在地", - "@home_click_settings": { - "description": "「首頁」路徑 → 點擊設定所在地" - }, - "history_earthquake_intensity": "TREM 觀測網實測震度", - "@history_earthquake_intensity": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → TREM 觀測網實測震度" - }, - "history_earthquake_intensity_h2": "使用 JMA 震度標準 (0.3秒三分量合成加速度)", - "@history_earthquake_intensity_h2": { - "description": "「歷史」路徑 → 「震度速報」內容 → 「i」圖例 → 使用 JMA 震度標準 (0.3秒三分量合成加速度)" - }, - "history_seismic_intensity_reference": "本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。", - "@history_seismic_intensity_reference": { - "description": "「歷史」路徑 → 「震度速報」內容 → 資訊托盤 → 本資料係由 TREM-Net 觀測網自動觀測結果所得,尚未經人為檢視確認,僅供應變之初步參考。實際應以中央氣象署發布之資訊為準。" - }, - "map_no_data": "沒有有效資料可顯示", - "@map_no_data": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → 沒有有效資料可顯示" - }, - "map_hh_time": "HH時", - "@map_hh_time": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → HH時" - }, - "ranking": "排行榜", - "@ranking": { - "description": "「排行榜」頁面 → 標題" - }, - "ranking_time": "資料時間:{time}\n共 {ranked_length} 觀測點", - "@ranking_time": { - "description": "「排行榜」頁面 → 資料時間:{time}\n共 {ranked_length} 觀測點", - "placeholders": { - "time": { - "type": "String" - }, - "ranked_length": { - "type": "String" - } - } - }, - "according": "依", - "@according": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 依" - }, - "ranking_descending": "降冪", - "@ranking_descending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 降冪" - }, - "ranking_ascending": "升冪", - "@ranking_ascending": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 升冪" - }, - "ranking_merge_into": "合併至", - "@ranking_merge_into": { - "description": "「排行榜」頁面 → 氣溫/風速資訊頁面 → 合併至" - }, - "permission_storage": "儲存", - "@permission_storage": { - "description": "「歡迎」頁面 → 儲存" - }, - "hours_24_trend": "24小時{type}趨勢", - "@hours_24_trend": { - "description": "「地圖」路徑 → 地圖列表 → 氣溫 → 點擊測站 → 資訊托盤 → '24小時${dataTypeToChineseMap[selectedDataType]}趨勢", - "placeholders": { - "type": { - "type": "String" - } - } - }, - "power_saving_position": "省電策略", - "@power_saving_position": { - "description": "「歡迎」頁面 → 省電策略" - }, - "power_saving_position_text": "允許 DPIP 在背景中持續運行,以便即時防災通知資訊。", - "@power_saving_position_text": { - "description": "「歡迎」頁面 → 允許DPIP在背景中持續運行,以便即時防災通知資訊。" - }, - "automatic_start_position": "自動化啟動", - "@automatic_start_position": { - "description": "「歡迎」頁面 → 自動化啟動" - }, - "automatic_start_position_text": "允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。", - "@automatic_start_position_text": { - "description": "「歡迎」頁面 → 允許 DPIP 在設備重新啟動或關閉後自動啟動,以持續提供防災通知服務。" - }, - "notify_eew": "緊急地震速報", - "@notify_eew": { - "description": "「設定」頁面 → 通知設定 → 緊急地震速報" - }, - "notify_monitor": "強震監視器", - "@notify_monitor": { - "description": "「設定」頁面 → 通知設定 → 強震監視器" - }, - "notify_report": "地震報告", - "@notify_eew": { - "description": "「設定」頁面 → 通知設定 → 地震報告" - }, - "notify_intensity": "震度速報", - "@notify_intensity": { - "description": "「設定」頁面 → 通知設定 → 震度速報" - }, - "notify_thunderstorm": "雷雨即時訊息", - "@notify_thunderstorm": { - "description": "「設定」頁面 → 通知設定 → 雷雨即時訊息" - }, - "notify_advisory": "天氣警特報", - "@notify_advisory": { - "description": "「設定」頁面 → 通知設定 → 天氣警特報" - }, - "notify_evacuation": "避難資訊", - "@notify_evacuation": { - "description": "「設定」頁面 → 通知設定 → 避難資訊" - }, - "notify_tsunami": "海嘯資訊", - "@notify_tsunami": { - "description": "「設定」頁面 → 通知設定 → 海嘯資訊" - } -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 31ababf27..805ea30c7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,20 +37,22 @@ void main() async { }; await Global.init(); - await DeviceInfo.init(); await Preference.init(); GlobalProviders.init(); - await AppLocalizations.load(); - initializeTimeZones(); - await initializeInstallationData(); - - await fcmInit(); - await notifyInit(); - initBackgroundService(); + await Future.wait([ + DeviceInfo.init(), + AppLocalizations.load(), + LocationNameLocalizations.load(), + WeatherStationLocalizations.load(), + initializeInstallationData(), + fcmInit(), + notifyInit(), + updateInfoToServer(), + ]); - await updateInfoToServer(); + await LocationServiceManager.initalize(); runApp( I18n( diff --git a/lib/models/data.dart b/lib/models/data.dart index e043d11f4..a3ddfb663 100644 --- a/lib/models/data.dart +++ b/lib/models/data.dart @@ -1,7 +1,12 @@ import 'dart:async'; import 'dart:collection'; +import 'dart:math'; + +import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; +import 'package:geojson_vi/geojson_vi.dart'; + import 'package:dpip/api/exptech.dart'; import 'package:dpip/api/model/eew.dart'; import 'package:dpip/api/model/report/earthquake_report.dart'; @@ -12,10 +17,10 @@ import 'package:dpip/api/model/weather/rain.dart'; import 'package:dpip/api/model/weather/weather.dart'; import 'package:dpip/core/eew.dart'; import 'package:dpip/global.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/log.dart'; import 'package:dpip/utils/map_utils.dart'; -import 'package:flutter/material.dart'; class _DpipDataModel extends ChangeNotifier { Map _station = {}; @@ -283,10 +288,20 @@ class DpipDataModel extends _DpipDataModel { for (final MapEntry(key: id, value: s) in station.entries) { if (s.work == false) continue; + + final coordinates = s.info.last.latlng.asGeoJsonCooridnate; + + // Create displaced coordinates with ~5 meter random offset + final random = Random(); + final offsetLng = (random.nextDouble() - 0.5) * 0.00009; // ~5m longitude offset + final offsetLat = (random.nextDouble() - 0.5) * 0.00009; // ~5m latitude offset + final displacedCoordinates = [coordinates[0] + offsetLng, coordinates[1] + offsetLat]; + final feature = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(s.info.last.latlng.toGeoJsonCoordinates() as List) + ..setGeometry(displacedCoordinates) ..setId(int.parse(id)) + ..setProperty('id', id) ..setProperty('net', s.net) ..setProperty('code', s.info.last.code); @@ -302,6 +317,13 @@ class DpipDataModel extends _DpipDataModel { } } + final location = Global.location['${s.info.last.code}']; + if (location != null) { + feature + ..setProperty('city', location.cityWithLevel) + ..setProperty('town', location.townWithLevel); + } + builder.addFeature(feature); } @@ -327,8 +349,9 @@ class DpipDataModel extends _DpipDataModel { final epicenter = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(e.info.latlng.toGeoJsonCoordinates() as List) + ..setGeometry(e.info.latlng.asGeoJsonCooridnate) ..setProperty('type', 'x'); + builder.addFeature(epicenter); } @@ -343,7 +366,7 @@ class DpipDataModel extends _DpipDataModel { if (s.work == false) continue; final feature = GeoJsonFeatureBuilder(GeoJsonFeatureType.Point) - ..setGeometry(s.info.last.latlng.toGeoJsonCoordinates() as List) + ..setGeometry(s.info.last.latlng.asGeoJsonCooridnate) ..setId(int.parse(id)) ..setProperty('net', s.net) ..setProperty('code', s.info.last.code); @@ -368,14 +391,15 @@ class DpipDataModel extends _DpipDataModel { final builder = GeoJsonBuilder(); if (rts != null && rts.box.isNotEmpty) { - for (final area in Global.box['features']) { - final id = area['properties']['ID'].toString(); + for (final area in Global.boxGeojson.features) { + if (area == null) continue; + + final id = area.properties!['ID'].toString(); if (!rts.box.containsKey(id)) continue; - final coordinates = - (area['geometry']['coordinates'][0] as List) - .map((e) => (e as List).map((n) => n as double).toList()) - .toList(); + final geometry = area.geometry! as GeoJSONPolygon; + + final coordinates = geometry.coordinates[0]; if (eew.isNotEmpty == true) { final eewMap = {for (final e in eew) e.id: e}; diff --git a/lib/models/settings/location.dart b/lib/models/settings/location.dart index 02ef53eca..90958a072 100644 --- a/lib/models/settings/location.dart +++ b/lib/models/settings/location.dart @@ -1,69 +1,196 @@ -import 'dart:developer'; +import 'dart:collection'; -import 'package:dpip/core/preference.dart'; import 'package:flutter/material.dart'; + import 'package:maplibre_gl/maplibre_gl.dart'; -class SettingsLocationModel extends ChangeNotifier { - void _log(String message) => log(message, name: 'SettingsLocationModel'); +import 'package:dpip/core/preference.dart'; +import 'package:dpip/global.dart'; - bool get _auto => Preference.locationAuto ?? false; - final ValueNotifier codeNotifier = ValueNotifier(Preference.locationCode); - final ValueNotifier coordinateNotifier = ValueNotifier( - LatLng(Preference.locationLatitude ?? 0, Preference.locationLongitude ?? 0), - ); - double? get _oldLongitude => Preference.locationOldLongitude; - double? get _oldLatitude => Preference.locationOldLatitude; +class _SettingsLocationModel extends ChangeNotifier { + /// The underlying [ValueNotifier] for the current location represented as a postal code. + /// + /// Returns the stored location code from preferences. Returns `null` if no location code has been set. + final $code = ValueNotifier(Preference.locationCode); - /// 自動定位 + /// The current location represented as a postal code. /// - /// 預設:不自動定位 - bool get auto => _auto; - void setAuto(bool value) { - Preference.locationAuto = value; - _log('Changed ${PreferenceKeys.locationAuto} to ${Preference.locationAuto}'); - notifyListeners(); - } + /// Returns the stored location code from preferences. Returns `null` if no location code has been set. + String? get code => $code.value; - /// 縣市代碼 - String? get code => Preference.locationCode; + /// Sets the current location using a postal code. + /// + /// [value] The postal code to set as the current location. + /// + /// Invoking this method will also update [$code] and notify all attached listeners. + /// + /// If [value] matches the current code, no changes are made. When [auto] is false, also updates the stored latitude + /// and longitude based on the location data associated with the postal code. void setCode(String? value) { + if (code == value) return; + + final location = Global.location[value]; + + // Check if the location is invalid + if (location == null) { + Preference.locationCode = null; + $code.value = null; + + if (!auto) { + Preference.locationLatitude = null; + Preference.locationLongitude = null; + + $coordinates.value = null; + } + + notifyListeners(); + return; + } + Preference.locationCode = value; - codeNotifier.value = value; - _log('Changed ${PreferenceKeys.locationCode} to ${Preference.locationCode}'); + $code.value = value; + + if (!auto) { + Preference.locationLatitude = location.lat; + Preference.locationLongitude = location.lng; + + $coordinates.value = LatLng(location.lat, location.lng); + } + notifyListeners(); } - /// 經度 - double? get longitude => Preference.locationLongitude; + /// The underlying [ValueNotifier] for the current location represented as a [LatLng] coordinate. + /// + /// Returns a [LatLng] object containing the stored coordinates for the current [code]. Returns `null` if either + /// latitude or longitude is not set. + /// + /// This is used to display the precise location of the user on the map. + /// + /// Depends on [code]. + final $coordinates = ValueNotifier( + Preference.locationLatitude != null && Preference.locationLongitude != null + ? LatLng(Preference.locationLatitude!, Preference.locationLongitude!) + : null, + ); - /// 緯度 - double? get latitude => Preference.locationLatitude; - void setLatLng({double? latitude, double? longitude}) { - Preference.locationLatitude = latitude; - _log('Changed ${PreferenceKeys.locationLatitude} to ${Preference.locationLatitude}'); + /// The current location represented as a LatLng coordinate. + /// + /// Returns a [LatLng] object containing the stored coordinates for the current [code]. Returns `null` if either + /// latitude or longitude is not set. + /// + /// This is used to display the precise location of the user on the map. + /// + /// Depends on [code]. + LatLng? get coordinates => $coordinates.value; - Preference.locationLongitude = longitude; - _log('Changed ${PreferenceKeys.locationLongitude} to ${Preference.locationLongitude}'); + /// Sets the current location using a LatLng coordinate. + /// + /// Takes a [LatLng] value containing latitude and longitude coordinates and updates the stored location preferences. + /// If value is `null`, both latitude and longitude will be set to `null`. + /// + /// Invoking this method will also update [$coordinates] and notify all attached listeners. + /// + /// This method should be called aside with [setCode] if automatic location update is enabled. + /// + /// Use [setCode] instead when automatic location update is disabled. + void setCoordinates(LatLng? value) { + Preference.locationLatitude = value?.latitude; + Preference.locationLongitude = value?.longitude; - coordinateNotifier.value = LatLng(latitude ?? 0, longitude ?? 0); + $coordinates.value = value; notifyListeners(); } - /// 經度 - double? get oldLongitude => _oldLongitude; - void setOldLongitude(double? value) { - Preference.locationOldLongitude = value; - _log('Changed ${PreferenceKeys.locationOldLongitude} to ${Preference.locationOldLongitude}'); + /// The underlying [ValueNotifier] for the current state of automatic location update. + /// + /// Returns a [bool] indicating if automatic location update is enabled. When enabled, the app will use GPS to + /// automatically update the current location. When disabled, the location must be set manually either by [setCode] or + /// [setCoordinates]. + /// + /// Defaults to `false` if no preference has been set. + final $auto = ValueNotifier(Preference.locationAuto ?? false); + + /// The current state of automatic location update. + /// + /// Returns a [bool] indicating if automatic location update is enabled. When enabled, the app will use GPS to + /// automatically update the current location. When disabled, the location must be set manually either by [setCode] or + /// [setCoordinates]. + /// + /// Defaults to `false` if no preference has been set. + bool get auto => $auto.value; + + /// Sets whether location should be automatically determined using GPS. + /// + /// Takes a [bool] value indicating if automatic location detection should be enabled. When enabled, the app will use + /// GPS to automatically determine and update the current location. When disabled, the location must be set manually. + void setAuto(bool value) { + Preference.locationAuto = value; + + $auto.value = value; + notifyListeners(); } - /// 緯度 - double? get oldLatitude => _oldLatitude; - void setOldLatitude(double? value) { - Preference.locationOldLatitude = value; - _log('Changed ${PreferenceKeys.locationOldLatitude} to ${Preference.locationOldLatitude}'); + /// The underlying [ValueNotifier] for the list of favorited locations. + /// + /// Returns a [List] of [String] containing the postal codes of the favorited locations. + /// + /// Defaults to an empty list if no favorited locations have been set. + final $favorited = ValueNotifier(Preference.locationFavorited.toSet()); + + /// The list of favorited locations. + /// + /// Returns a [UnmodifiableSetView] containing the postal codes of the favorited locations. + /// + /// Defaults to an empty [Set] if no favorited locations have been set. + UnmodifiableSetView get favorited => UnmodifiableSetView($favorited.value); + + /// Adds a location to the list of favorited locations. + /// + /// Takes a [String] value representing the postal code of the location to add to the list. + /// + /// If the location is already favorited, this method will do nothing. + void favorite(String code) { + final list = {...Preference.locationFavorited}..add(code); + + Preference.locationFavorited = list.toList(); + + $favorited.value = list; + + notifyListeners(); + } + + /// Removes a location from the list of favorited locations. + /// + /// Takes a [String] value representing the postal code of the location to remove from the list. + /// + /// If the location is not favorited, this method will do nothing. + void unfavorite(String code) { + final list = {...Preference.locationFavorited}..remove(code); + + Preference.locationFavorited = list.toList(); + + $favorited.value = list; + notifyListeners(); } + + /// Refreshes the location settings from preferences. + /// + /// Updates the [code], [coordinates], and [auto] properties to reflect the current preferences. + /// + /// This method is used to refresh the location settings when the preferences are updated. + void refresh() { + $code.value = Preference.locationCode; + $coordinates.value = + Preference.locationLatitude != null && Preference.locationLongitude != null + ? LatLng(Preference.locationLatitude!, Preference.locationLongitude!) + : null; + $auto.value = Preference.locationAuto ?? false; + $favorited.value = Preference.locationFavorited.toSet(); + } } + +class SettingsLocationModel extends _SettingsLocationModel {} diff --git a/lib/models/settings/map.dart b/lib/models/settings/map.dart index 7d8f72119..2bb0f7710 100644 --- a/lib/models/settings/map.dart +++ b/lib/models/settings/map.dart @@ -40,4 +40,16 @@ class SettingsMapModel extends ChangeNotifier { _log('Changed ${PreferenceKeys.mapLayers} to $value'); notifyListeners(); } + + /// Refreshes the map settings from preferences. + /// + /// Updates the [updateInterval], [baseMap], and [layers] properties to reflect the current preferences. + /// + /// This method is used to refresh the map settings when the preferences are updated. + void refresh() { + updateIntervalNotifier.value = Preference.mapUpdateFps ?? 10; + baseMapNotifier.value = BaseMapType.values.asNameMap()[Preference.mapBase] ?? BaseMapType.exptech; + layersNotifier.value = + Preference.mapLayers?.split(',').map((v) => MapLayer.values.byName(v)).toSet() ?? {MapLayer.monitor}; + } } diff --git a/lib/route/event_viewer/intensity.dart b/lib/route/event_viewer/intensity.dart index 24dce69d3..41b6df762 100644 --- a/lib/route/event_viewer/intensity.dart +++ b/lib/route/event_viewer/intensity.dart @@ -15,9 +15,9 @@ import 'package:dpip/core/ios_get_location.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/global.dart'; import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/intensity_color.dart'; import 'package:dpip/utils/list_icon.dart'; -import 'package:dpip/utils/need_location.dart'; import 'package:dpip/utils/parser.dart'; import 'package:dpip/widgets/chip/label_chip.dart'; import 'package:dpip/widgets/list/detail_field_tile.dart'; @@ -55,36 +55,11 @@ class _IntensityPageState extends State { _mapController = controller; } - Future _addUserLocationMarker() async { - if (isUserLocationValid) { - await _mapController.removeLayer('markers'); - await _mapController.addLayer( - 'markers-geojson', - 'markers', - const SymbolLayerProperties( - symbolZOrder: 'source', - iconSize: [ - Expressions.interpolate, - ['linear'], - [Expressions.zoom], - 5, - 0.5, - 10, - 1.5, - ], - iconImage: 'gps', - iconAllowOverlap: true, - iconIgnorePlacement: true, - ), - ); - } - } - Future _loadMap() async { radarList = await ExpTech().getRadarList(); if (Platform.isIOS && GlobalProviders.location.auto) { - await getSavedLocation(); + await updateSavedLocationIOS(); } await _mapController.addSource( @@ -96,37 +71,14 @@ class _IntensityPageState extends State { } Future start() async { - userLat = GlobalProviders.location.latitude ?? 0; - userLon = GlobalProviders.location.longitude ?? 0; - - isUserLocationValid = userLon != 0 && userLat != 0; - - if (isUserLocationValid) { - await _mapController.setGeoJsonSource('markers-geojson', { - 'type': 'FeatureCollection', - 'features': [ - { - 'type': 'Feature', - 'properties': {}, - 'geometry': { - 'coordinates': [userLon, userLat], - 'type': 'Point', - }, - }, - ], - }); - final cameraUpdate = CameraUpdate.newLatLngZoom(LatLng(userLat, userLon), 8); - await _mapController.animateCamera(cameraUpdate, duration: const Duration(milliseconds: 1000)); - } + final location = GlobalProviders.location.coordinates; - if (!isUserLocationValid && !GlobalProviders.location.auto) { - await showLocationDialog(context); + if (location != null && location.isValid) { + await _mapController.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); + } else { + await _mapController.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); } - await _addUserLocationMarker(); - - setState(() {}); - getEventInfo(); if (!widget.item.addition.isFinal) { @@ -385,7 +337,7 @@ class _IntensityPageState extends State { } Widget _buildAffectedAreas() { - final grouped = groupBy(data.area.map((e) => Global.location[e.toString()]!), (e) => e.city); + final grouped = groupBy(data.area.map((e) => Global.location[e.toString()]!), (e) => e.cityWithLevel); final List areas = []; for (final MapEntry(key: city, value: locations) in grouped.entries) { @@ -413,7 +365,7 @@ class _IntensityPageState extends State { side: BorderSide(color: context.colors.outline), backgroundColor: context.colors.surfaceContainerHigh, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - label: Text(e.town), + label: Text(e.townWithLevel), ); }).toList(), ), diff --git a/lib/route/event_viewer/thunderstorm.dart b/lib/route/event_viewer/thunderstorm.dart index 8bbf20bb4..d8c3de40c 100644 --- a/lib/route/event_viewer/thunderstorm.dart +++ b/lib/route/event_viewer/thunderstorm.dart @@ -12,18 +12,17 @@ import 'package:timezone/timezone.dart'; import 'package:dpip/api/exptech.dart'; import 'package:dpip/api/model/history/history.dart'; -import 'package:dpip/app_old/page/map/radar/radar.dart'; +import 'package:dpip/api/route.dart'; +import 'package:dpip/app/map/_widgets/map_legend.dart'; import 'package:dpip/core/ios_get_location.dart'; import 'package:dpip/core/providers.dart'; import 'package:dpip/global.dart'; import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/list_icon.dart'; -import 'package:dpip/utils/need_location.dart'; import 'package:dpip/utils/parser.dart'; -import 'package:dpip/utils/radar_color.dart'; import 'package:dpip/widgets/chip/label_chip.dart'; import 'package:dpip/widgets/list/detail_field_tile.dart'; -import 'package:dpip/widgets/map/legend.dart'; import 'package:dpip/widgets/map/map.dart'; import 'package:dpip/widgets/sheet/bottom_sheet_drag_handle.dart'; @@ -39,8 +38,8 @@ class ThunderstormPage extends StatefulWidget { class _ThunderstormPageState extends State { late MapLibreMapController _mapController; List radarList = []; - double userLat = 0; - double userLon = 0; + double? userLat; + double? userLon; bool isUserLocationValid = false; bool _showLegend = false; Timer? _blinkTimer; @@ -54,10 +53,6 @@ class _ThunderstormPageState extends State { super.dispose(); } - String getTileUrl(String timestamp) { - return 'https://api-1.exptech.dev/api/v1/tiles/radar/$timestamp/{z}/{x}/{y}.png'; - } - void _initMap(MapLibreMapController controller) { _mapController = controller; } @@ -65,7 +60,7 @@ class _ThunderstormPageState extends State { Future _loadMap() async { radarList = await ExpTech().getRadarList(); - final String newTileUrl = getTileUrl(radarList.last); + final String newTileUrl = Routes.radarTile(radarList.last); await _mapController.addSource('radarSource', RasterSourceProperties(tiles: [newTileUrl], tileSize: 256)); @@ -100,7 +95,7 @@ class _ThunderstormPageState extends State { ); if (Platform.isIOS && GlobalProviders.location.auto) { - await getSavedLocation(); + await updateSavedLocationIOS(); } await _mapController.addSource( @@ -122,34 +117,13 @@ class _ThunderstormPageState extends State { } Future start() async { - userLat = GlobalProviders.location.latitude ?? 0; - userLon = GlobalProviders.location.longitude ?? 0; - - isUserLocationValid = userLon != 0 && userLat != 0; - - if (isUserLocationValid) { - await _mapController.setGeoJsonSource('markers-geojson', { - 'type': 'FeatureCollection', - 'features': [ - { - 'type': 'Feature', - 'properties': {}, - 'geometry': { - 'coordinates': [userLon, userLat], - 'type': 'Point', - }, - }, - ], - }); - final cameraUpdate = CameraUpdate.newLatLngZoom(LatLng(userLat, userLon), 8); - await _mapController.animateCamera(cameraUpdate, duration: const Duration(milliseconds: 1000)); - } + final location = GlobalProviders.location.coordinates; - if (!isUserLocationValid && !GlobalProviders.location.auto) { - await showLocationDialog(context); + if (location != null && location.isValid) { + await _mapController.animateCamera(CameraUpdate.newLatLngZoom(location, 7.4)); + } else { + await _mapController.animateCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.4)); } - - setState(() {}); } void _toggleLegend() { @@ -159,32 +133,29 @@ class _ThunderstormPageState extends State { } Widget _buildLegend() { - return MapLegend( - children: [ - _buildColorBar(), - const SizedBox(height: 8), - _buildColorBarLabels(), - const SizedBox(height: 12), - Text('單位:dBZ', style: context.theme.textTheme.labelMedium), + return ColorLegend( + reverse: true, + unit: 'dBZ', + items: [ + ColorLegendItem(color: const Color(0xff00ffff), value: 0), + ColorLegendItem(color: const Color(0xff00a3ff), value: 5), + ColorLegendItem(color: const Color(0xff005bff), value: 10), + ColorLegendItem(color: const Color(0xff0000ff), value: 15, blendTail: false), + ColorLegendItem(color: const Color(0xff00ff00), value: 16, hidden: true), + ColorLegendItem(color: const Color(0xff00d300), value: 20), + ColorLegendItem(color: const Color(0xff00a000), value: 25), + ColorLegendItem(color: const Color(0xffccea00), value: 30), + ColorLegendItem(color: const Color(0xffffd300), value: 35), + ColorLegendItem(color: const Color(0xffff8800), value: 40), + ColorLegendItem(color: const Color(0xffff1800), value: 45), + ColorLegendItem(color: const Color(0xffd30000), value: 50), + ColorLegendItem(color: const Color(0xffa00000), value: 55), + ColorLegendItem(color: const Color(0xffea00cc), value: 60), + ColorLegendItem(color: const Color(0xff9600ff), value: 65), ], ); } - Widget _buildColorBar() { - return SizedBox(height: 20, width: 300, child: CustomPaint(painter: ColorBarPainter(dBZColors))); - } - - Widget _buildColorBarLabels() { - final labels = List.generate(14, (index) => (index * 5).toString()); - return SizedBox( - width: 300, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: labels.map((label) => Text(label, style: const TextStyle(fontSize: 9))).toList(), - ), - ); - } - @override Widget build(BuildContext context) { final TZDateTime radarDateTime = TZDateTime.fromMillisecondsSinceEpoch( @@ -424,7 +395,7 @@ class _ThunderstormPageState extends State { } Widget _buildAffectedAreas() { - final grouped = groupBy(widget.item.area.map((e) => Global.location[e.toString()]!), (e) => e.city); + final grouped = groupBy(widget.item.area.map((e) => Global.location[e.toString()]!), (e) => e.cityWithLevel); final List areas = []; for (final MapEntry(key: city, value: locations) in grouped.entries) { @@ -452,7 +423,7 @@ class _ThunderstormPageState extends State { side: BorderSide(color: context.colors.outline), backgroundColor: context.colors.surfaceContainerHigh, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - label: Text(e.town), + label: Text(e.townWithLevel), ); }).toList(), ), diff --git a/lib/route/report/report.dart b/lib/route/report/report.dart index 496ff04ed..0e7f9334e 100644 --- a/lib/route/report/report.dart +++ b/lib/route/report/report.dart @@ -11,6 +11,7 @@ import 'package:dpip/core/eew.dart'; import 'package:dpip/route/report/report_sheet_content.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/color_scheme.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/intensity_color.dart'; import 'package:dpip/utils/log.dart'; @@ -96,7 +97,7 @@ class _ReportRouteState extends State with TickerProviderStateMixin 'properties': { 'intensity': 10, // 10 is for classifying epicenter cross }, - 'geometry': {'coordinates': data.latlng.toGeoJsonCoordinates(), 'type': 'Point'}, + 'geometry': {'coordinates': data.latlng.asGeoJsonCooridnate, 'type': 'Point'}, }); expandBounds(bounds, data.latlng); diff --git a/lib/router.dart b/lib/router.dart index 76f5c2de6..cb2aea8e0 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -38,8 +38,10 @@ import 'package:dpip/app/welcome/layout.dart'; import 'package:dpip/core/i18n.dart'; import 'package:dpip/core/preference.dart'; import 'package:dpip/route/announcement/announcement.dart'; +import 'package:dpip/utils/constants.dart'; +import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/log.dart'; -import 'package:dpip/widgets/transitions/forward_back.dart'; +import 'package:dpip/widgets/shell_wrapper.dart'; final GlobalKey _rootNavigatorKey = GlobalKey(); final GlobalKey _welcomeNavigatorKey = GlobalKey(); @@ -51,45 +53,28 @@ final router = GoRouter( routes: [ ShellRoute( navigatorKey: _welcomeNavigatorKey, - builder: (context, state, child) => WelcomeLayout(child: child), + builder: (context, state, child) => ShellWrapper(WelcomeLayout(child: child)), routes: [ - GoRoute( - path: WelcomeAboutPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomeAboutPage()), - ), + GoRoute(path: WelcomeAboutPage.route, builder: (context, state) => const Material(child: WelcomeAboutPage())), GoRoute( path: WelcomeExpTechPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomeExpTechPage()), - ), - GoRoute( - path: WelcomeNoticePage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomeNoticePage()), + builder: (context, state) => const Material(child: WelcomeExpTechPage()), ), + GoRoute(path: WelcomeNoticePage.route, builder: (context, state) => const Material(child: WelcomeNoticePage())), GoRoute( path: WelcomePermissionPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const WelcomePermissionPage()), + builder: (context, state) => const Material(child: WelcomePermissionPage()), ), ], ), - GoRoute( - path: HomePage.route, - pageBuilder: (context, state) => const NoTransitionPage( - child: AppLayout( - child: HomePage(), - ), - ), - ), + GoRoute(path: HomePage.route, builder: (context, state) => const AppLayout(child: HomePage())), ShellRoute( navigatorKey: _settingsNavigatorKey, builder: (context, state, child) { final title = switch (state.fullPath) { SettingsLocationPage.route => '所在地'.i18n, - SettingsLocationSelectPage.route => '所在地'.i18n, - final p when p == SettingsLocationSelectCityPage.route() => '所在地'.i18n, + SettingsLocationSelectPage.route => '新增地點'.i18n, + final p when p == SettingsLocationSelectCityPage.route() => '新增地點'.i18n, SettingsThemePage.route => '主題'.i18n, SettingsThemeSelectPage.route => '主題'.i18n, SettingsLocalePage.route => '語言'.i18n, @@ -104,136 +89,99 @@ final router = GoRouter( SettingsNotifyIntensityPage.route => '震度速報'.i18n, SettingsNotifyThunderstormPage.route => '雷雨即時訊息'.i18n, SettingsNotifyAdvisoryPage.route => '天氣警特報'.i18n, - SettingsNotifyEvacuationPage.route => '避難資訊'.i18n, + SettingsNotifyEvacuationPage.route => '防災資訊'.i18n, SettingsNotifyTsunamiPage.route => '海嘯資訊'.i18n, SettingsNotifyAnnouncementPage.route => '公告'.i18n, SettingsDonatePage.route => '贊助我們'.i18n, _ => '設定'.i18n, }; - return SettingsLayout(title: title, child: child); + + return ShellWrapper( + SettingsLayout( + title: title, + child: Theme( + data: context.theme.copyWith(pageTransitionsTheme: kFadeForwardPageTransitionsTheme), + child: child, + ), + ), + ); }, routes: [ - GoRoute( - path: SettingsIndexPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsIndexPage()), - ), + GoRoute(path: SettingsIndexPage.route, builder: (context, state) => const Material(child: SettingsIndexPage())), GoRoute( path: SettingsLocationPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocationPage()), + builder: (context, state) => const Material(child: SettingsLocationPage()), ), GoRoute( path: SettingsLocationSelectPage.route, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocationSelectPage()), + builder: (context, state) => const Material(child: SettingsLocationSelectPage()), ), GoRoute( path: SettingsLocationSelectCityPage.route(), - pageBuilder: - (context, state) => ForwardBackTransitionPage( - key: state.pageKey, - child: SettingsLocationSelectCityPage(city: state.pathParameters['city']!), - ), - ), - GoRoute( - path: SettingsThemePage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsThemePage()), + builder: + (context, state) => Material(child: SettingsLocationSelectCityPage(city: state.pathParameters['city']!)), ), + GoRoute(path: SettingsThemePage.route, builder: (context, state) => const Material(child: SettingsThemePage())), GoRoute( path: SettingsThemeSelectPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsThemeSelectPage()), + builder: (context, state) => const Material(child: SettingsThemeSelectPage()), ), GoRoute( path: SettingsLocalePage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocalePage()), + builder: (context, state) => const Material(child: SettingsLocalePage()), ), GoRoute( path: SettingsLocaleSelectPage.route, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsLocaleSelectPage()), - ), - GoRoute( - path: SettingsUnitPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsUnitPage()), - ), - GoRoute( - path: SettingsMapPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsMapPage()), + builder: (context, state) => const Material(child: SettingsLocaleSelectPage()), ), + GoRoute(path: SettingsUnitPage.route, builder: (context, state) => const Material(child: SettingsUnitPage())), + GoRoute(path: SettingsMapPage.route, builder: (context, state) => const Material(child: SettingsMapPage())), GoRoute( path: SettingsNotifyPage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyPage()), + builder: (context, state) => const Material(child: SettingsNotifyPage()), routes: [ GoRoute( path: SettingsNotifyEewPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyEewPage()), + builder: (context, state) => const Material(child: SettingsNotifyEewPage()), ), GoRoute( path: SettingsNotifyMonitorPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyMonitorPage()), + builder: (context, state) => const Material(child: SettingsNotifyMonitorPage()), ), GoRoute( path: SettingsNotifyReportPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyReportPage()), + builder: (context, state) => const Material(child: SettingsNotifyReportPage()), ), GoRoute( path: SettingsNotifyIntensityPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyIntensityPage()), + builder: (context, state) => const Material(child: SettingsNotifyIntensityPage()), ), GoRoute( path: SettingsNotifyThunderstormPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyThunderstormPage()), + builder: (context, state) => const Material(child: SettingsNotifyThunderstormPage()), ), GoRoute( path: SettingsNotifyAdvisoryPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyAdvisoryPage()), + builder: (context, state) => const Material(child: SettingsNotifyAdvisoryPage()), ), GoRoute( path: SettingsNotifyEvacuationPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyEvacuationPage()), + builder: (context, state) => const Material(child: SettingsNotifyEvacuationPage()), ), GoRoute( path: SettingsNotifyTsunamiPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyTsunamiPage()), + builder: (context, state) => const Material(child: SettingsNotifyTsunamiPage()), ), GoRoute( path: SettingsNotifyAnnouncementPage.name, - pageBuilder: - (context, state) => - ForwardBackTransitionPage(key: state.pageKey, child: const SettingsNotifyAnnouncementPage()), + builder: (context, state) => const Material(child: SettingsNotifyAnnouncementPage()), ), ], ), GoRoute( path: SettingsDonatePage.route, - pageBuilder: - (context, state) => ForwardBackTransitionPage(key: state.pageKey, child: const SettingsDonatePage()), + builder: (context, state) => const Material(child: SettingsDonatePage()), ), ], ), diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 689f497bc..ba328d90e 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -1,6 +1,23 @@ import 'package:flutter/material.dart'; + import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:dpip/widgets/transitions/predictive_fade_forward.dart'; + +const kZoomPageTransitionsTheme = PageTransitionsTheme( + builders: { + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), + }, +); + +const kFadeForwardPageTransitionsTheme = PageTransitionsTheme( + builders: { + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + TargetPlatform.android: PredictiveBackFadeForwardPageTransitionsBuilder(), + }, +); + const kEmphasizedAnimationStyle = AnimationStyle( curve: Easing.emphasizedDecelerate, duration: Durations.medium4, @@ -15,7 +32,17 @@ const kSymbolIconSize = [ ['linear'], [Expressions.zoom], 5, - 0.1, - 10, + 0.2, + 15, 0.6, ]; + +const kCircleIconSize = [ + Expressions.interpolate, + ['linear'], + [Expressions.zoom], + 5, + 2, + 15, + 12, +]; diff --git a/lib/utils/depth_color.dart b/lib/utils/depth_color.dart index 2349ee7d7..5e538355b 100644 --- a/lib/utils/depth_color.dart +++ b/lib/utils/depth_color.dart @@ -1,33 +1,26 @@ import 'dart:ui'; -class DepthColor { - static const depth0 = Color(0xFF000000); - static const depth1 = Color(0xFFFF0000); - static const depth2 = Color(0xFFFF6400); - static const depth3 = Color(0xFFFFC800); - static const depth4 = Color(0xFF00C800); - static const depth5 = Color(0xFF00C8C8); - static const depth6 = Color(0xFF0000C8); +const kDepthColor0 = Color(0xFF000000); +const kDepthColor1 = Color(0xFFFF0000); +const kDepthColor2 = Color(0xFFFF6400); +const kDepthColor3 = Color(0xFFFFC800); +const kDepthColor4 = Color(0xFF00C800); +const kDepthColor5 = Color(0xFF00C8C8); +const kDepthColor6 = Color(0xFF0000C8); - static Color depth(double depth) { - final depthList = [5, 15, 30, 50, 100, 150]; - final colorList = [depth1, depth2, depth3, depth4, depth5, depth6]; +Color getDepthColor(double depth) { + final depthList = [5, 15, 30, 50, 100, 150]; + final colorList = [kDepthColor1, kDepthColor2, kDepthColor3, kDepthColor4, kDepthColor5, kDepthColor6]; - if (depth <= depthList.first) { - return colorList.first; - } + if (depth <= depthList.first) return colorList.first; - if (depth >= depthList.last) { - return colorList.last; - } + if (depth >= depthList.last) return colorList.last; - for (int i = 0; i < depthList.length - 1; i++) { - if (depth >= depthList[i] && depth < depthList[i + 1]) { - final double localT = (depth - depthList[i]) / (depthList[i + 1] - depthList[i]); - return Color.lerp(colorList[i], colorList[i + 1], localT)!; - } + for (int i = 0; i < depthList.length - 1; i++) { + if (depth >= depthList[i] && depth < depthList[i + 1]) { + final double localT = (depth - depthList[i]) / (depthList[i + 1] - depthList[i]); + return Color.lerp(colorList[i], colorList[i + 1], localT)!; } - - return depth0; } + return kDepthColor0; } diff --git a/lib/utils/extensions/build_context.dart b/lib/utils/extensions/build_context.dart index 33f733320..49275edb2 100644 --- a/lib/utils/extensions/build_context.dart +++ b/lib/utils/extensions/build_context.dart @@ -2,11 +2,9 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:dpip/l10n/app_localizations.dart'; import 'package:dpip/utils/extensions/go_router.dart'; extension CommonContext on BuildContext { - AppLocalizations get i18n => AppLocalizations.of(this)!; ThemeData get theme => Theme.of(this); NavigatorState get navigator => Navigator.of(this); ColorScheme get colors => Theme.of(this).colorScheme; diff --git a/lib/utils/extensions/datetime.dart b/lib/utils/extensions/datetime.dart index c1b962781..a944d7724 100644 --- a/lib/utils/extensions/datetime.dart +++ b/lib/utils/extensions/datetime.dart @@ -4,9 +4,16 @@ import 'package:i18n_extension/i18n_extension.dart'; import 'package:intl/intl.dart'; import 'package:timezone/timezone.dart'; +extension DateTimeExtension on DateTime { + String toSimpleDateTimeString() => DateFormat('MM/dd HH:mm').format(this); + String toLocaleFullDateString(BuildContext context) => + DateFormat('yyyy/MM/dd (EEEE)', context.locale.toLanguageTag()).format(this); + String toDateTimeString() => DateFormat('yyyy/MM/dd HH:mm:ss').format(this); + String toLocaleTimeString() => DateFormat('HH:mm:ss').format(this); +} + extension TZDateTimeExtension on TZDateTime { - String toSimpleDateTimeString(BuildContext context) => - DateFormat('MM/dd HH:mm', context.locale.toLanguageTag()).format(this); + String toSimpleDateTimeString() => DateFormat('MM/dd HH:mm').format(this); String toLocaleFullDateString(BuildContext context) => DateFormat('yyyy/MM/dd (EEEE)', context.locale.toLanguageTag()).format(this); String toLocaleDateTimeString(BuildContext context) => diff --git a/lib/utils/extensions/int.dart b/lib/utils/extensions/int.dart index 416d6d29a..9e3956d70 100644 --- a/lib/utils/extensions/int.dart +++ b/lib/utils/extensions/int.dart @@ -23,7 +23,9 @@ extension CommonContext on int { ][this]; String get asIntensityDisplayLabel => ['0', '1', '2', '3', '4', '5⁻', '5⁺', '6⁻', '6⁺', '7'][this]; TZDateTime get asTZDateTime => parseDateTime(this); - String toSimpleDateTimeString(BuildContext context) => asTZDateTime.toSimpleDateTimeString(context); + int get asFahrenheit => (this * 9 / 5 + 32).round(); + + String toSimpleDateTimeString() => asTZDateTime.toSimpleDateTimeString(); String toLocaleFullDateString(BuildContext context) => asTZDateTime.toLocaleFullDateString(context); String toLocaleDateTimeString(BuildContext context) => asTZDateTime.toLocaleDateTimeString(context); String toLocaleTimeString(BuildContext context) => asTZDateTime.toLocaleTimeString(context); diff --git a/lib/utils/extensions/latlng.dart b/lib/utils/extensions/latlng.dart index e427a854d..1dcefdd97 100644 --- a/lib/utils/extensions/latlng.dart +++ b/lib/utils/extensions/latlng.dart @@ -1,5 +1,4 @@ -import 'dart:math'; - +import 'package:geolocator/geolocator.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:dpip/utils/geojson.dart'; @@ -7,21 +6,21 @@ import 'package:dpip/utils/geojson.dart'; extension GeoJsonLatLng on LatLng { bool get isValid => latitude != 0 && longitude != 0; - GeoJsonFeatureBuilder toFeatureBuilder() { - return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point)..setGeometry(toGeoJsonCoordinates() as List); - } + List get asGeoJsonCooridnate => [longitude, latitude]; - double to(LatLng other) { - final lat1 = latitude * pi / 180; - final lat2 = other.latitude * pi / 180; - final lon1 = longitude * pi / 180; - final lon2 = other.longitude * pi / 180; + GeoJsonFeatureBuilder toGeoJsonFeatureBuilder() { + return GeoJsonFeatureBuilder(GeoJsonFeatureType.Point)..setGeometry(asGeoJsonCooridnate); + } - final dlon = lon2 - lon1; - final dlat = lat2 - lat1; - final a = sin(dlat / 2) * sin(dlat / 2) + cos(lat1) * cos(lat2) * sin(dlon / 2) * sin(dlon / 2); - final c = 2 * atan2(sqrt(a), sqrt(1 - a)); + GeoJsonBuilder toGeoJsonBuilder() { + return GeoJsonBuilder()..addFeature(toGeoJsonFeatureBuilder()); + } - return 6371.0 * c; + Map toGeoJsonMap() { + return toGeoJsonBuilder().build(); } + + /// Calculates the distance between the supplied coordinates in meters. The distance between the coordinates is + /// calculated using the Haversine formula (see https://en.wikipedia.org/wiki/Haversine_formula). + double to(LatLng other) => Geolocator.distanceBetween(latitude, longitude, other.latitude, other.longitude); } diff --git a/lib/utils/extensions/maplibre.dart b/lib/utils/extensions/maplibre.dart new file mode 100644 index 000000000..9492091fb --- /dev/null +++ b/lib/utils/extensions/maplibre.dart @@ -0,0 +1,62 @@ +import 'package:maplibre_gl/maplibre_gl.dart'; + +import 'package:dpip/widgets/map/map.dart'; + +extension MapLibreMapControllerExtension on MapLibreMapController { + Future setBaseMap(BaseMapType baseMapType) async { + await Future.wait([ + setOSMVisibility(baseMapType == BaseMapType.osm), + setGoogleVisibility(baseMapType == BaseMapType.google), + setExptechVisibility(baseMapType == BaseMapType.exptech), + ]); + } + + Future setOSMVisibility(bool visible) async { + final layers = (await getLayerIds()).cast(); + final osmLayers = layers.where((v) => v.startsWith('osm-')); + + await Future.wait(osmLayers.map((v) => setLayerVisibility(v, visible))); + } + + Future setGoogleVisibility(bool visible) async { + final layers = (await getLayerIds()).cast(); + final googleLayers = layers.where((v) => v.startsWith('google-')); + + await Future.wait(googleLayers.map((v) => setLayerVisibility(v, visible))); + } + + Future setExptechVisibility(bool visible) async { + final layers = (await getLayerIds()).cast(); + final exptechLayers = layers.where((v) => v.startsWith('exptech-')); + + await Future.wait(exptechLayers.map((v) => setLayerVisibility(v, visible))); + } + + /// Checks if the provided [id] exists in the map as a source or layer. + /// + /// By default, checks both sources and layers. Use [source] and [layer] + /// parameters to limit the search scope: + /// - If [source] is `true`, only sources will be checked + /// - If [layer] is `true`, only layers will be checked + /// - If both are `true`, both sources and layers will be checked + /// + /// Returns `true` if the [id] exists in any of the checked categories, otherwise, returns `false`. + Future exists(String id, {bool? source, bool? layer}) async { + final shouldCheckBoth = source == null && layer == null; + + final checkSource = shouldCheckBoth || (source ?? false); + final checkLayer = shouldCheckBoth || (layer ?? false); + + if (checkSource) { + final sourceIds = await getSourceIds(); + if (sourceIds.contains(id)) return true; + } + + if (checkLayer) { + final layerIds = await getLayerIds(); + if (layerIds.contains(id)) return true; + } + + return false; + } +} diff --git a/lib/utils/extensions/preference.dart b/lib/utils/extensions/preference.dart index c2ab5ceff..6ef63541f 100644 --- a/lib/utils/extensions/preference.dart +++ b/lib/utils/extensions/preference.dart @@ -1,5 +1,7 @@ import 'package:shared_preferences/shared_preferences.dart'; +import 'package:dpip/utils/log.dart'; + extension PreferenceExtension on SharedPreferencesWithCache { /// Sets a value of any supported type to SharedPreferences. /// @@ -16,23 +18,30 @@ extension PreferenceExtension on SharedPreferencesWithCache { /// /// If [value] is null or omitted, the key will be removed from SharedPreferences. Future set(String key, [T? value]) { - if (value == null) { - return remove(key); - } + try { + if (value == null) { + return remove(key); + } - switch (value) { - case String(): - return setString(key, value); - case int(): - return setInt(key, value); - case bool(): - return setBool(key, value); - case double(): - return setDouble(key, value); - case List(): - return setStringList(key, value); - default: - throw ArgumentError.value(value, 'value', 'Unsupported type: ${value.runtimeType}'); + switch (value) { + case String(): + return setString(key, value); + case int(): + return setInt(key, value); + case bool(): + return setBool(key, value); + case double(): + return setDouble(key, value); + case List(): + return setStringList(key, value); + default: + throw ArgumentError.value(value, 'value', 'Unsupported type: ${value.runtimeType}'); + } + } catch (e, s) { + TalkerManager.instance.error('💾 $key set to "$value" FAILED', e, s); + rethrow; + } finally { + TalkerManager.instance.info('💾 $key set to "$value"'); } } } diff --git a/lib/utils/extensions/state.dart b/lib/utils/extensions/state.dart new file mode 100644 index 000000000..a22df27d3 --- /dev/null +++ b/lib/utils/extensions/state.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +extension StateExtension on State { + @protected + // ignore: invalid_use_of_protected_member + void rebuild([void Function()? fn]) => setState(fn ?? () {}); +} diff --git a/lib/utils/extensions/string.dart b/lib/utils/extensions/string.dart index eaaba9b36..6d4547aa9 100644 --- a/lib/utils/extensions/string.dart +++ b/lib/utils/extensions/string.dart @@ -1,3 +1,5 @@ +import 'package:dpip/api/model/location/location.dart'; +import 'package:dpip/global.dart'; import 'package:flutter/widgets.dart'; import 'package:dpip/utils/extensions/build_context.dart'; @@ -15,10 +17,13 @@ extension StringExtension on String { String toLocaleFullDateString(BuildContext context) => asInt.asTZDateTime.toLocaleFullDateString(context); String toLocaleTimeString(BuildContext context) => asInt.asTZDateTime.toLocaleTimeString(context); - String toSimpleDateTimeString(BuildContext context) => asInt.asTZDateTime.toSimpleDateTimeString(context); + String toSimpleDateTimeString() => asInt.asTZDateTime.toSimpleDateTimeString(); Text get asText => Text(this); TextSpan get asTextSpan => TextSpan(text: this); + + Location getLocation() => Global.location[this]!; + Location? get asLocation => Location.tryParse(this); } extension TextExtension on Text { diff --git a/lib/utils/geojson.dart b/lib/utils/geojson.dart index 260b7626d..7f5217355 100644 --- a/lib/utils/geojson.dart +++ b/lib/utils/geojson.dart @@ -62,7 +62,7 @@ class GeoJsonFeatureBuilder { } GeoJsonFeatureBuilder setProperty(String key, dynamic value) { - this.properties[key] = value; + properties[key] = value; return this; } diff --git a/lib/utils/location_to_code.dart b/lib/utils/location_to_code.dart deleted file mode 100644 index 0cb648846..000000000 --- a/lib/utils/location_to_code.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/services.dart' show rootBundle; - -class GeoJsonProperties { - final String town; - final String county; - final String name; - final int code; - - GeoJsonProperties({required this.town, required this.county, required this.name, required this.code}); - - factory GeoJsonProperties.fromJson(Map json) { - return GeoJsonProperties( - town: json['TOWN'] as String, - county: json['COUNTY'] as String, - name: json['NAME'] as String, - code: json['CODE'] as int, - ); - } - - @override - String toString() { - return 'GeoJsonProperties(town: $town, county: $county, name: $name, code: $code)'; - } -} - -class GeoJsonHelper { - static Map? _geoJsonData; - - static Future loadGeoJson(String geojsonAssetPath) async { - final String geojsonStr = await rootBundle.loadString(geojsonAssetPath); - _geoJsonData = json.decode(geojsonStr); - } - - static GeoJsonProperties? checkPointInPolygons(double lat, double lng) { - if (_geoJsonData == null) return null; - for (final feature in _geoJsonData!['features']) { - if (feature['geometry']['type'] == 'Polygon' || feature['geometry']['type'] == 'MultiPolygon') { - final List>> polygons = _getPolygons(feature['geometry']); - - for (final polygon in polygons) { - if (_isPointInPolygon(lat, lng, polygon)) { - return GeoJsonProperties.fromJson(feature['properties']); - } - } - } - } - return null; - } - - static List>> _getPolygons(Map geometry) { - final List>> polygons = []; - - if (geometry['type'] == 'Polygon') { - polygons.add(_convertToDoubleList(geometry['coordinates'][0])); - } else if (geometry['type'] == 'MultiPolygon') { - for (final polygon in geometry['coordinates']) { - polygons.add(_convertToDoubleList(polygon[0])); - } - } - - return polygons; - } - - static List> _convertToDoubleList(List coordinates) { - return coordinates.map>((coord) { - if (coord is List) { - return coord.map((e) => e is num ? e.toDouble() : 0.0).toList(); - } else { - return [0.0, 0.0]; - } - }).toList(); - } - - static bool _isPointInPolygon(double lat, double lng, List> polygon) { - bool isInside = false; - int j = polygon.length - 1; - for (int i = 0; i < polygon.length; i++) { - final double xi = polygon[i][0]; - final double yi = polygon[i][1]; - final double xj = polygon[j][0]; - final double yj = polygon[j][1]; - - final bool intersect = ((yi > lat) != (yj > lat)) && (lng < (xj - xi) * (lat - yi) / (yj - yi) + xi); - if (intersect) isInside = !isInside; - - j = i; - } - return isInside; - } -} diff --git a/lib/utils/map_utils.dart b/lib/utils/map_utils.dart index 8c05bb7ce..4578aa129 100644 --- a/lib/utils/map_utils.dart +++ b/lib/utils/map_utils.dart @@ -1,9 +1,12 @@ import 'dart:math'; +import 'package:geojson_vi/geojson_vi.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; + import 'package:dpip/api/model/eew.dart'; +import 'package:dpip/global.dart'; import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; List expandBounds(List bounds, LatLng point) { // [南西,北東] @@ -45,8 +48,6 @@ enum Units { degrees, } -const emptyGeoJson = {'type': 'FeatureCollection', 'features': []}; - /// Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth. /// /// @memberof helpers @@ -126,7 +127,7 @@ Map circle(LatLng center, double radius, {int steps = 64, Units for (var i = 0; i < steps; i++) { final point = destination(center, radius, (i * -360) / steps, units: units); - coordinates.add(point.toGeoJsonCoordinates()); + coordinates.add(point.asGeoJsonCooridnate); } coordinates.add(coordinates[0]); @@ -151,11 +152,11 @@ GeoJsonFeatureBuilder circleFeature({ }) { // main final polygon = GeoJsonFeatureBuilder(GeoJsonFeatureType.Polygon); - final List coordinates = []; + final List> coordinates = []; for (var i = 0; i < steps; i++) { final point = destination(center, radius, (i * -360) / steps, units: units); - coordinates.add(point.toGeoJsonCoordinates()); + coordinates.add(point.asGeoJsonCooridnate); } coordinates.add(coordinates[0]); @@ -163,7 +164,7 @@ GeoJsonFeatureBuilder circleFeature({ return polygon.setGeometry(coordinates); } -bool checkBoxSkip(Map eewLastInfo, Map eewDist, List box) { +bool checkBoxSkip(Map eewLastInfo, Map eewDist, List> box) { bool passed = false; for (final eew in eewLastInfo.keys) { @@ -184,3 +185,72 @@ bool checkBoxSkip(Map eewLastInfo, Map eewDist, Lis return passed; } + +String? getTownCodeFromCoordinates(LatLng target) { + final features = Global.townGeojson.features; + + for (final feature in features) { + if (feature == null) continue; + + final geometry = feature.geometry; + if (geometry == null) continue; + + bool isInPolygon = false; + + if (geometry is GeoJSONPolygon) { + final polygon = geometry.coordinates[0]; + + bool isInside = false; + int j = polygon.length - 1; + for (int i = 0; i < polygon.length; i++) { + final double xi = polygon[i][0]; + final double yi = polygon[i][1]; + final double xj = polygon[j][0]; + final double yj = polygon[j][1]; + + final bool intersect = + ((yi > target.latitude) != (yj > target.latitude)) && + (target.longitude < (xj - xi) * (target.latitude - yi) / (yj - yi) + xi); + if (intersect) isInside = !isInside; + + j = i; + } + isInPolygon = isInside; + } + + if (geometry is GeoJSONMultiPolygon) { + final multiPolygon = geometry.coordinates; + + for (final polygonCoordinates in multiPolygon) { + final polygon = polygonCoordinates[0]; + + bool isInside = false; + int j = polygon.length - 1; + for (int i = 0; i < polygon.length; i++) { + final double xi = polygon[i][0]; + final double yi = polygon[i][1]; + final double xj = polygon[j][0]; + final double yj = polygon[j][1]; + + final bool intersect = + ((yi > target.latitude) != (yj > target.latitude)) && + (target.longitude < (xj - xi) * (target.latitude - yi) / (yj - yi) + xi); + if (intersect) isInside = !isInside; + + j = i; + } + + if (isInside) { + isInPolygon = true; + break; + } + } + } + + if (isInPolygon) { + return feature.properties!['CODE']?.toString(); + } + } + + return null; +} diff --git a/lib/utils/radar_color.dart b/lib/utils/radar_color.dart index 24d4cd062..e03b7a0c1 100644 --- a/lib/utils/radar_color.dart +++ b/lib/utils/radar_color.dart @@ -1,68 +1,68 @@ final List dBZColors = [ - '00ffff', - '00ecff', - '00daff', - '00c8ff', - '00b6ff', - '00a3ff', - '0091ff', - '007fff', - '006dff', - '005bff', - '0048ff', - '0036ff', - '0024ff', - '0012ff', - '0000ff', - '00ff00', - '00f400', - '00e900', - '00de00', - '00d300', + '00ffff', // 0 + '00ecff', // + '00daff', // + '00c8ff', // + '00b6ff', // + '00a3ff', // 5 + '0091ff', // + '007fff', // + '006dff', // + '005bff', // 10 + '0048ff', // + '0036ff', // + '0024ff', // + '0012ff', // + '0000ff', // 15 + '00ff00', // 16 + '00f400', // 17 + '00e900', // 18 + '00de00', // + '00d300', // 20 '00c800', '00be00', '00b400', '00aa00', - '00a000', + '00a000', // 25 '009600', '33ab00', '66c000', '99d500', - 'ccea00', + 'ccea00', // 30 'ffff00', 'fff400', 'ffe900', 'ffde00', - 'ffd300', + 'ffd300', // 35 'ffc800', 'ffb800', 'ffa800', 'ff9800', - 'ff8800', + 'ff8800', // 40 'ff7800', 'ff6000', 'ff4800', 'ff3000', - 'ff1800', + 'ff1800', // 45 'ff0000', 'f40000', 'e90000', 'de0000', - 'd30000', + 'd30000', // 50 'c80000', 'be0000', 'b40000', 'aa0000', - 'a00000', + 'a00000', // 55 '960000', 'ab0033', 'c00066', 'd50099', - 'ea00cc', + 'ea00cc', // 60 'ff00ff', 'ea00ff', 'd500ff', 'c000ff', - 'ab00ff', + 'ab00ff', // 65 '9600ff', ]; diff --git a/lib/widgets/blurred_container.dart b/lib/widgets/blurred_container.dart new file mode 100644 index 000000000..8e6ad5c42 --- /dev/null +++ b/lib/widgets/blurred_container.dart @@ -0,0 +1,40 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +import 'package:dpip/utils/extensions/build_context.dart'; + +class BlurredContainer extends StatelessWidget { + final Widget child; + final EdgeInsets padding; + final Color? shadowColor; + final double elevation; + final double sigma; + + const BlurredContainer({ + super.key, + required this.child, + this.padding = const EdgeInsets.all(8), + this.shadowColor, + this.elevation = 0, + this.sigma = 16, + }); + + @override + Widget build(BuildContext context) { + return Material( + color: context.colors.surfaceContainer.withValues(alpha: 0.6), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide(color: context.colors.outline.withValues(alpha: 0.2)), + ), + elevation: elevation, + shadowColor: shadowColor ?? context.colors.shadow.withValues(alpha: 0.4), + clipBehavior: Clip.antiAlias, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: sigma, sigmaY: sigma), + child: Padding(padding: padding, child: child), + ), + ); + } +} diff --git a/lib/widgets/home/event_list_route.dart b/lib/widgets/home/event_list_route.dart index d43b78c6a..916ef3434 100644 --- a/lib/widgets/home/event_list_route.dart +++ b/lib/widgets/home/event_list_route.dart @@ -41,6 +41,9 @@ void handleEventList(BuildContext context, History history) { case HistoryType.extremelyTorrentialRain: page = ThunderstormPage(item: history); + case HistoryType.workAndClassSuspension: + page = ThunderstormPage(item: history); + case HistoryType.earthquake: context.push( MapPage.route( diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart index c699b7484..0a00a8e76 100644 --- a/lib/widgets/layout.dart +++ b/lib/widgets/layout.dart @@ -161,7 +161,7 @@ class _HorizontalLayout { ); } - Widget call({Key? key, required List children, EdgeInsets? padding}) { + Widget call({Key? key, Iterable children = const [], EdgeInsets? padding}) { final widget = Row( key: key, mainAxisAlignment: mainAxisAlignment, @@ -171,7 +171,7 @@ class _HorizontalLayout { verticalDirection: verticalDirection, textBaseline: textBaseline, spacing: spacing, - children: children, + children: children is List ? children : children.toList(), ); if (padding != null) { @@ -183,6 +183,9 @@ class _HorizontalLayout { _HorizontalLayout get left => copyWith(mainAxisAlignment: MainAxisAlignment.start); _HorizontalLayout get right => copyWith(mainAxisAlignment: MainAxisAlignment.end); + _HorizontalLayout get between => copyWith(mainAxisAlignment: MainAxisAlignment.spaceBetween); + _HorizontalLayout get around => copyWith(mainAxisAlignment: MainAxisAlignment.spaceAround); + _HorizontalLayout get evenly => copyWith(mainAxisAlignment: MainAxisAlignment.spaceEvenly); _HorizontalLayout get top => copyWith(crossAxisAlignment: CrossAxisAlignment.start); _HorizontalLayout get bottom => copyWith(crossAxisAlignment: CrossAxisAlignment.end); _HorizontalLayout get center => copyWith(crossAxisAlignment: CrossAxisAlignment.center); diff --git a/lib/widgets/list/list_tile.dart b/lib/widgets/list/list_tile.dart index 073a0c789..2704c0281 100644 --- a/lib/widgets/list/list_tile.dart +++ b/lib/widgets/list/list_tile.dart @@ -32,6 +32,7 @@ class ListSectionTile extends StatelessWidget { title: Text(title, style: titleStyle ?? const TextStyle(fontWeight: FontWeight.bold)), subtitle: subtitle, trailing: trailing, + contentPadding: const EdgeInsets.symmetric(horizontal: 16), enabled: enabled, visualDensity: VisualDensity.comfortable, onTap: onTap, diff --git a/lib/widgets/map/map.dart b/lib/widgets/map/map.dart index 2b393b535..c403cb158 100644 --- a/lib/widgets/map/map.dart +++ b/lib/widgets/map/map.dart @@ -1,18 +1,18 @@ -import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'package:flutter/material.dart'; + +import 'package:async/async.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; + import 'package:dpip/core/ios_get_location.dart'; import 'package:dpip/core/providers.dart'; -import 'package:dpip/utils/constants.dart'; import 'package:dpip/utils/extensions/build_context.dart'; import 'package:dpip/utils/extensions/latlng.dart'; import 'package:dpip/utils/geojson.dart'; import 'package:dpip/utils/log.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:maplibre_gl/maplibre_gl.dart'; -import 'package:path_provider/path_provider.dart'; +import 'package:dpip/widgets/map/style.dart'; enum BaseMapType { exptech, osm, google } @@ -36,9 +36,6 @@ class BaseMapLayerIds { static const exptechCountyFill = 'exptech-county'; static const exptechCountyOutline = 'exptech-county-outline'; - static const osmGlobalRaster = 'osm-global'; - static const googleGlobalRaster = 'google-global'; - static const userLocation = 'user-location'; static Iterable values() sync* { @@ -69,14 +66,16 @@ class DpipMap extends StatefulWidget { /// Whether to set camera focus to user location when the user longitude or latitude is updated. /// /// Default is `false`. - final bool focusUserLocationOnValueUpdate; + final bool focusUserLocationWhenUpdated; static const kTaiwanCenter = LatLng(23.60, 120.85); + static const kTaiwanZoom = 6.4; + static const kUserLocationZoom = 7.2; const DpipMap({ super.key, this.baseMapType = BaseMapType.exptech, - this.initialCameraPosition = const CameraPosition(target: kTaiwanCenter, zoom: 6.4), + this.initialCameraPosition = const CameraPosition(target: kTaiwanCenter, zoom: kTaiwanZoom), this.onMapCreated, this.onMapClick, this.onMapIdle, @@ -89,111 +88,13 @@ class DpipMap extends StatefulWidget { this.dragEnabled, this.scrollGesturesEnabled, this.tiltGesturesEnabled, - this.focusUserLocationOnValueUpdate = false, + this.focusUserLocationWhenUpdated = false, }); @override State createState() => DpipMapState(); -} - -class DpipMapState extends State { - String _getStyleJson(String spritePath) { - final colors = context.colors; - - return jsonEncode({ - 'version': 8, - 'name': 'ExpTech Studio', - 'center': [120.85, 23.10], - 'zoom': 6.2, - 'sources': { - 'map': { - 'type': 'vector', - 'url': 'https://lb.exptech.dev/api/v1/map/tiles/tiles.json', - 'tileSize': 512, - 'buffer': 64, - }, - 'osm': { - 'type': 'raster', - 'tiles': ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'], - 'tileSize': 256, - 'attribution': '© OpenStreetMap Contributors', - 'maxzoom': 19, - }, - 'google': { - 'type': 'raster', - 'tiles': ['https://mts1.google.com/vt/lyrs=p&hl=zh-TW&x={x}&y={y}&z={z}'], - 'tileSize': 256, - 'attribution': '© Google Maps', - 'maxzoom': 19, - }, - }, - 'sprite': spritePath, - 'glyphs': 'https://glyphs.geolonia.com/{fontstack}/{range}.pbf', - 'layers': [ - { - 'id': 'background', - 'type': 'background', - 'paint': {'background-color': colors.surface.toHexStringRGB()}, - }, - { - 'id': BaseMapLayerIds.osmGlobalRaster, - 'type': 'raster', - 'source': 'osm', - 'layout': {'visibility': widget.baseMapType == BaseMapType.osm ? 'visible' : 'none'}, - }, - { - 'id': BaseMapLayerIds.googleGlobalRaster, - 'type': 'raster', - 'source': 'google', - 'layout': {'visibility': widget.baseMapType == BaseMapType.google ? 'visible' : 'none'}, - }, - { - 'id': BaseMapLayerIds.exptechGlobalFill, - 'type': 'fill', - 'source': 'map', - 'source-layer': 'global', - 'paint': {'fill-color': colors.surfaceContainer.toHexStringRGB(), 'fill-opacity': 1}, - 'layout': {'visibility': widget.baseMapType == BaseMapType.exptech ? 'visible' : 'none'}, - }, - { - 'id': BaseMapLayerIds.exptechCountyFill, - 'type': 'fill', - 'source': 'map', - 'source-layer': 'city', - 'paint': {'fill-color': colors.surfaceContainerHigh.toHexStringRGB(), 'fill-opacity': 1}, - 'layout': {'visibility': widget.baseMapType == BaseMapType.exptech ? 'visible' : 'none'}, - }, - { - 'id': BaseMapLayerIds.exptechTownFill, - 'type': 'fill', - 'source': 'map', - 'source-layer': 'town', - 'paint': {'fill-color': colors.surfaceContainerHigh.toHexStringRGB(), 'fill-opacity': 1}, - 'layout': {'visibility': widget.baseMapType == BaseMapType.exptech ? 'visible' : 'none'}, - }, - { - 'id': BaseMapLayerIds.exptechCountyOutline, - 'source': 'map', - 'source-layer': 'city', - 'type': 'line', - 'paint': {'line-color': colors.outline.toHexStringRGB()}, - 'layout': {'visibility': 'visible'}, - }, - { - 'id': 'tsunami', - 'type': 'line', - 'source': 'map', - 'source-layer': 'tsunami', - 'paint': {'line-opacity': 0, 'line-width': 3, 'line-join': 'round'}, - }, - ], - }); - } - MapLibreMapController? _controller; - String? styleAbsoluteFilePath; - - double adjustedZoom(double zoom) { + static double adjustedZoom(BuildContext context, double zoom) { final double devicePixelRatio = MediaQuery.of(context).devicePixelRatio; const double baseZoomAdjustment = 1.0; const double mediumZoomAdjustment = 0.3; @@ -208,72 +109,34 @@ class DpipMapState extends State { return zoom + baseZoomAdjustment; } } +} + +class DpipMapState extends State { + MapLibreMapController? _controller; + Future? _stylePathFuture; Future _updateUserLocation() async { if (!mounted) return; - try { - final controller = _controller; - if (controller == null) return; + final controller = _controller; + if (controller == null) return; + try { if (Platform.isIOS && GlobalProviders.location.auto) { - await getSavedLocation(); + await updateSavedLocationIOS(); } - final location = GlobalProviders.location.coordinateNotifier.value; + final location = GlobalProviders.location.coordinates; - const sourceId = BaseMapSourceIds.userLocation; - const layerId = BaseMapLayerIds.userLocation; + final data = location?.toGeoJsonMap() ?? GeoJsonBuilder.empty; - final isSourceExists = (await controller.getSourceIds()).contains(sourceId); - final isLayerExists = (await controller.getLayerIds()).contains(layerId); + await controller.setGeoJsonSource(BaseMapSourceIds.userLocation, data); - if (!location.isValid) { - if (isLayerExists) { - await controller.removeLayer(layerId); - TalkerManager.instance.info('Removed Layer "$layerId"'); - } - - if (isSourceExists) { - await controller.removeSource(sourceId); - TalkerManager.instance.info('Removed Source "$sourceId"'); - } - - await controller.moveCamera(CameraUpdate.newLatLngZoom(DpipMap.kTaiwanCenter, 6.2)); - TalkerManager.instance.info('Moved Camera to ${DpipMap.kTaiwanCenter}'); - return; - } - - if (!isSourceExists) { - await controller.addSource( - sourceId, - GeojsonSourceProperties(data: GeoJsonBuilder().addFeature(location.toFeatureBuilder()).build()), - ); - TalkerManager.instance.info('Added Source "$sourceId"'); - } else { - await controller.setGeoJsonSource(sourceId, GeoJsonBuilder().addFeature(location.toFeatureBuilder()).build()); - TalkerManager.instance.info('Updated Source "$sourceId"'); + if (widget.focusUserLocationWhenUpdated) { + await controller.moveCamera(CameraUpdate.newLatLngZoom(location!, DpipMap.kUserLocationZoom)); } - - if (!isLayerExists) { - await controller.addLayer( - sourceId, - layerId, - const SymbolLayerProperties( - symbolZOrder: 'source', - iconImage: 'gps', - iconSize: kSymbolIconSize, - iconAllowOverlap: true, - iconIgnorePlacement: true, - ), - ); - TalkerManager.instance.info('Added Layer "$layerId"'); - } - - await controller.moveCamera(CameraUpdate.newLatLngZoom(location, 7)); - TalkerManager.instance.info('Moved Camera to $location'); } catch (e, s) { - TalkerManager.instance.error('DpipMap._updateUserLocation', e, s); + TalkerManager.instance.error('🗺️ failed to update user location', e, s); } } @@ -287,79 +150,97 @@ class DpipMapState extends State { void initState() { super.initState(); - GlobalProviders.location.coordinateNotifier.addListener(_updateUserLocation); + GlobalProviders.location.$coordinates.addListener(_updateUserLocation); + } + + ColorScheme? _lastColors; + CancelableOperation? _setThemeColorFuture; + Future setThemeColors(ColorScheme colors) async { + final controller = _controller; + if (controller == null) return; - getApplicationDocumentsDirectory().then((dir) async { - final documentDir = dir.path; - final mapDir = '$documentDir/map'; + final layers = [...MapStyle.osmLayers(colors), ...MapStyle.exptechLayers(colors)]; - await Directory(mapDir).create(recursive: true); + for (final layer in layers) { + if (layer['type'] == 'background') continue; - // Copy sprite.png - final spritePngData = await rootBundle.load('assets/sprites.png'); - final spritePngFile = File('$mapDir/sprites.png'); - await spritePngFile.writeAsBytes(spritePngData.buffer.asUint8List()); - final spritePngFile2x = File('$mapDir/sprites@2x.png'); - await spritePngFile2x.writeAsBytes(spritePngData.buffer.asUint8List()); - TalkerManager.instance.info('Copied sprite.png to $spritePngFile'); + final json = layer['paint'] as Map; + json.remove('visibility'); - // Copy sprite.json - final spriteJsonData = await rootBundle.load('assets/sprites.json'); - final spriteJsonFile = File('$mapDir/sprites.json'); - await spriteJsonFile.writeAsBytes(spriteJsonData.buffer.asUint8List()); - final spriteJsonFile2x = File('$mapDir/sprites@2x.json'); - await spriteJsonFile2x.writeAsBytes(spriteJsonData.buffer.asUint8List()); - TalkerManager.instance.info('Copied sprite.json to $spriteJsonFile'); + final properties = switch (layer['type']) { + 'fill' => FillLayerProperties.fromJson(json), + 'line' => LineLayerProperties.fromJson(json), + 'symbol' => SymbolLayerProperties.fromJson(json), + 'raster' => RasterLayerProperties.fromJson(json), + _ => null, + }; - final spriteUri = '${spriteJsonFile.parent.uri}sprites'; - TalkerManager.instance.info('Sprite is $spriteUri'); + await controller.setLayerProperties(layer['id'] as String, properties!); + } + } - // Create style.json - final styleJsonData = _getStyleJson(spriteUri); - final styleJsonFile = File('$mapDir/style.json'); - await styleJsonFile.writeAsString(styleJsonData); + @override + void didChangeDependencies() { + super.didChangeDependencies(); + + if (_stylePathFuture == null) { + _stylePathFuture = MapStyle(context, baseMap: widget.baseMapType).save(); + } else if (_lastColors != context.colors) { + _setThemeColorFuture?.cancel(); + _setThemeColorFuture = CancelableOperation.fromFuture(setThemeColors(context.colors)); + } - setState(() => styleAbsoluteFilePath = styleJsonFile.uri.toFilePath()); - }); + _lastColors = context.colors; } @override Widget build(BuildContext context) { - if (styleAbsoluteFilePath == null) { - return const Center(child: CircularProgressIndicator()); - } + final double adjustedZoomValue = DpipMap.adjustedZoom(context, widget.initialCameraPosition.zoom); - final double adjustedZoomValue = adjustedZoom(widget.initialCameraPosition.zoom); - - return MapLibreMap( - minMaxZoomPreference: widget.minMaxZoomPreference ?? const MinMaxZoomPreference(3, 9), - trackCameraPosition: true, - initialCameraPosition: CameraPosition(target: widget.initialCameraPosition.target, zoom: adjustedZoomValue), - styleString: styleAbsoluteFilePath!, - tiltGesturesEnabled: widget.tiltGesturesEnabled ?? false, - scrollGesturesEnabled: widget.scrollGesturesEnabled ?? true, - rotateGesturesEnabled: widget.rotateGesturesEnabled ?? false, - zoomGesturesEnabled: widget.zoomGesturesEnabled ?? true, - doubleClickZoomEnabled: widget.doubleClickZoomEnabled ?? true, - dragEnabled: widget.dragEnabled ?? true, - attributionButtonMargins: const Point(-100, -100), - onMapCreated: (controller) { - _controller = controller; - widget.onMapCreated?.call(controller); - }, - onMapClick: widget.onMapClick, - onMapIdle: widget.onMapIdle, - onMapLongClick: widget.onMapLongClick, - onStyleLoadedCallback: () { - _initMap(); - widget.onStyleLoadedCallback?.call(); + return FutureBuilder( + future: _stylePathFuture, + builder: (context, snapshot) { + final styleString = snapshot.data; + + if (styleString == null) { + return const Center(child: CircularProgressIndicator()); + } + + return ColoredBox( + color: context.colors.surface, + child: MapLibreMap( + minMaxZoomPreference: widget.minMaxZoomPreference ?? const MinMaxZoomPreference(4, 12.5), + trackCameraPosition: true, + initialCameraPosition: CameraPosition(target: widget.initialCameraPosition.target, zoom: adjustedZoomValue), + styleString: styleString, + tiltGesturesEnabled: widget.tiltGesturesEnabled ?? false, + scrollGesturesEnabled: widget.scrollGesturesEnabled ?? true, + rotateGesturesEnabled: widget.rotateGesturesEnabled ?? false, + zoomGesturesEnabled: widget.zoomGesturesEnabled ?? true, + doubleClickZoomEnabled: widget.doubleClickZoomEnabled ?? true, + dragEnabled: widget.dragEnabled ?? true, + attributionButtonMargins: const Point(-100, -100), + onMapCreated: (controller) { + _controller = controller; + widget.onMapCreated?.call(controller); + }, + onMapClick: widget.onMapClick, + onMapIdle: widget.onMapIdle, + onMapLongClick: widget.onMapLongClick, + onStyleLoadedCallback: () { + _initMap(); + widget.onStyleLoadedCallback?.call(); + }, + translucentTextureSurface: true, + ), + ); }, ); } @override void dispose() { - GlobalProviders.location.coordinateNotifier.removeListener(_updateUserLocation); + GlobalProviders.location.$coordinates.removeListener(_updateUserLocation); super.dispose(); } } diff --git a/lib/widgets/map/style.dart b/lib/widgets/map/style.dart new file mode 100644 index 000000000..287932efb --- /dev/null +++ b/lib/widgets/map/style.dart @@ -0,0 +1,1139 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; + +import 'package:crypto/crypto.dart'; +import 'package:maplibre_gl/maplibre_gl.dart'; +import 'package:path_provider/path_provider.dart'; + +import 'package:dpip/utils/constants.dart'; +import 'package:dpip/utils/extensions/build_context.dart'; +import 'package:dpip/utils/extensions/latlng.dart'; +import 'package:dpip/utils/geojson.dart'; +import 'package:dpip/widgets/map/map.dart'; + +class MapStyle { + late Map json; + + MapStyle(BuildContext context, {required BaseMapType baseMap}) { + json = { + 'version': 8, + 'name': 'DPIP Map', + 'center': DpipMap.kTaiwanCenter.asGeoJsonCooridnate, + 'zoom': DpipMap.adjustedZoom(context, DpipMap.kTaiwanZoom), + 'font-faces': { + 'Noto Sans TC Regular': + 'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk/blob/Sans/OTF/TraditionalChinese/NotoSansCJKtc-Regular.otf', + 'Noto Sans TC Bold': + 'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk/blob/Sans/OTF/TraditionalChinese/NotoSansCJKtc-Bold.otf', + }, + 'glyphs': 'https://cdn.jsdelivr.net/gh/exptechtw/map-assets/{fontstack}/{range}.pbf', + 'sprite': 'https://cdn.jsdelivr.net/gh/exptechtw/map-assets/sprites', + 'sources': {...osmSource(), ...googleSource(), ...exptechSource(), ...locationSource()}, + 'layers': [ + background(), + ...osmLayers(context.colors, visible: baseMap == BaseMapType.osm), + ...googleLayers(visible: baseMap == BaseMapType.google), + ...exptechLayers(context.colors, visible: baseMap == BaseMapType.exptech), + locationLayer(), + ], + }; + } + + Future save() async { + final cache = await getApplicationCacheDirectory(); + final cachePath = cache.path; + + final data = jsonEncode(json); + final hash = md5.convert(utf8.encode(data)).toString(); + + final styleJsonFile = File('$cachePath/map-$hash.json'); + + if (!styleJsonFile.existsSync()) { + await styleJsonFile.writeAsString(data); + } + + return styleJsonFile.path; + } + + static Map osmSource() => { + 'ne2_shaded': { + 'maxzoom': 6, + 'tileSize': 256, + 'tiles': ['https://tiles.openfreemap.org/natural_earth/ne2sr/{z}/{x}/{y}.png'], + 'type': 'raster', + }, + 'openmaptiles': {'type': 'vector', 'url': 'https://tiles.openfreemap.org/planet', 'volatile': true}, + }; + + static Map background() => { + 'id': 'background', + 'type': 'background', + 'paint': {'background-opacity': 0}, + 'layout': {'visibility': 'visible'}, + }; + + static List> osmLayers(ColorScheme colors, {bool visible = false}) => [ + { + 'id': 'osm-landcover-glacier', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'landcover', + 'filter': [ + '==', + ['get', 'subclass'], + 'glacier', + ], + 'paint': { + 'fill-color': '#fff', + 'fill-opacity': [ + 'interpolate', + ['linear'], + ['zoom'], + 0, + 0.9, + 10, + 0.3, + ], + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-park', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'park', + 'filter': [ + 'match', + ['geometry-type'], + ['MultiPolygon', 'Polygon'], + true, + false, + ], + 'paint': { + 'fill-color': '#d8e8c8', + 'fill-opacity': [ + 'interpolate', + ['exponential', 1.8], + ['zoom'], + 9, + if (colors.brightness == Brightness.dark) 0.05 else 0.6, + 12, + if (colors.brightness == Brightness.dark) 0.004 else 0.25, + ], + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-landcover-wood', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'landcover', + 'filter': [ + '==', + ['get', 'class'], + 'wood', + ], + 'paint': { + 'fill-antialias': [ + 'step', + ['zoom'], + false, + 9, + true, + ], + 'fill-color': '#66aa44', + 'fill-opacity': 0.1, + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-landcover-grass', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'landcover', + 'filter': [ + '==', + ['get', 'class'], + 'grass', + ], + 'paint': {'fill-color': '#d2e8c2', 'fill-opacity': colors.brightness == Brightness.dark ? 0.2 : 1}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-landcover-grass-park', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'park', + 'filter': [ + '==', + ['get', 'class'], + 'public_park', + ], + 'paint': {'fill-color': '#d8e8c8', 'fill-opacity': colors.brightness == Brightness.dark ? 0.4 : 0.8}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway_tunnel', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'minzoom': 14, + 'filter': [ + 'all', + [ + 'match', + ['get', 'class'], + ['canal', 'river', 'stream'], + true, + false, + ], + [ + '==', + ['get', 'brunnel'], + 'tunnel', + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-dasharray': [2, 4], + 'line-width': [ + 'interpolate', + ['exponential', 1.3], + ['zoom'], + 13, + 0.5, + 20, + 6, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway-other', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'filter': [ + 'all', + [ + 'match', + ['get', 'class'], + ['canal', 'river', 'stream'], + false, + true, + ], + [ + '==', + ['get', 'intermittent'], + 0, + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-width': [ + 'interpolate', + ['exponential', 1.3], + ['zoom'], + 13, + 0.5, + 20, + 2, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway-other-intermittent', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'filter': [ + 'all', + [ + 'match', + ['get', 'class'], + ['canal', 'river', 'stream'], + false, + true, + ], + [ + '==', + ['get', 'intermittent'], + 1, + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-dasharray': [4, 3], + 'line-width': [ + 'interpolate', + ['exponential', 1.3], + ['zoom'], + 13, + 0.5, + 20, + 2, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway-stream-canal', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'filter': [ + 'all', + [ + 'match', + ['get', 'class'], + ['canal', 'stream'], + true, + false, + ], + [ + '!=', + ['get', 'brunnel'], + 'tunnel', + ], + [ + '==', + ['get', 'intermittent'], + 0, + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-width': [ + 'interpolate', + ['exponential', 1.3], + ['zoom'], + 13, + 0.5, + 20, + 6, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway-stream-canal-intermittent', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'filter': [ + 'all', + [ + 'match', + ['get', 'class'], + ['canal', 'stream'], + true, + false, + ], + [ + '!=', + ['get', 'brunnel'], + 'tunnel', + ], + [ + '==', + ['get', 'intermittent'], + 1, + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-dasharray': [4, 3], + 'line-width': [ + 'interpolate', + ['exponential', 1.3], + ['zoom'], + 13, + 0.5, + 20, + 6, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway-river', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'river', + ], + [ + '!=', + ['get', 'brunnel'], + 'tunnel', + ], + [ + '!=', + ['get', 'intermittent'], + 1, + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-width': [ + 'interpolate', + ['exponential', 1.2], + ['zoom'], + 10, + 0.8, + 20, + 6, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway-river-intermittent', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'river', + ], + [ + '!=', + ['get', 'brunnel'], + 'tunnel', + ], + [ + '==', + ['get', 'intermittent'], + 1, + ], + ], + 'paint': { + 'line-color': '#a0c8f0', + 'line-opacity': colors.brightness == Brightness.dark ? 0.4 : 1, + 'line-dasharray': [3, 2.5], + 'line-width': [ + 'interpolate', + ['exponential', 1.2], + ['zoom'], + 10, + 0.8, + 20, + 6, + ], + }, + 'layout': {'line-cap': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-water', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'water', + 'filter': [ + 'all', + [ + '!=', + ['get', 'intermittent'], + 1, + ], + [ + '!=', + ['get', 'brunnel'], + 'tunnel', + ], + ], + 'paint': { + 'fill-color': colors.brightness == Brightness.dark ? colors.surfaceContainer.toHexStringRGB() : '#AECFE2', + 'fill-outline-color': colors.brightness == Brightness.dark ? colors.outline.toHexStringRGB() : '#AECFE2', + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-water-intermittent', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'water', + 'filter': [ + '==', + ['get', 'intermittent'], + 1, + ], + 'paint': {'fill-color': '#CFE6F7', 'fill-opacity': colors.brightness == Brightness.dark ? 0.3 : 0.7}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-landcover-ice-shelf', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'landcover', + 'filter': [ + '==', + ['get', 'subclass'], + 'ice_shelf', + ], + 'paint': { + 'fill-color': colors.brightness == Brightness.dark ? colors.surfaceContainerHigh.toHexStringRGB() : '#fff', + 'fill-opacity': [ + 'interpolate', + ['linear'], + ['zoom'], + 0, + 0.9, + 10, + 0.3, + ], + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-landcover-sand', + 'type': 'fill', + 'source': 'openmaptiles', + 'source-layer': 'landcover', + 'filter': [ + '==', + ['get', 'class'], + 'sand', + ], + 'paint': {'fill-color': '#f5eebc', 'fill-opacity': colors.brightness == Brightness.dark ? 0.6 : 1}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-boundary_3', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'boundary', + 'minzoom': 4, + 'filter': [ + 'all', + [ + '>=', + ['get', 'admin_level'], + 3, + ], + [ + '<=', + ['get', 'admin_level'], + 6, + ], + [ + '!=', + ['get', 'maritime'], + 1, + ], + [ + '!=', + ['get', 'disputed'], + 1, + ], + [ + '!', + ['has', 'claimed_by'], + ], + ], + 'paint': { + 'line-color': colors.outline.toHexStringRGB(), + 'line-dasharray': [1, 1], + 'line-width': [ + 'interpolate', + ['linear', 1], + ['zoom'], + 7, + 1, + 11, + 2, + ], + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-boundary_2', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'boundary', + 'filter': [ + 'all', + [ + '==', + ['get', 'admin_level'], + 2, + ], + [ + '!=', + ['get', 'maritime'], + 1, + ], + [ + '!=', + ['get', 'disputed'], + 1, + ], + [ + '!', + ['has', 'claimed_by'], + ], + ], + 'paint': { + 'line-color': colors.outlineVariant.toHexStringRGB(), + 'line-opacity': [ + 'interpolate', + ['linear'], + ['zoom'], + 0, + 0.4, + 4, + 1, + ], + 'line-width': [ + 'interpolate', + ['linear'], + ['zoom'], + 3, + 1, + 5, + 1.2, + 12, + 3, + ], + }, + 'layout': {'line-cap': 'round', 'line-join': 'round', 'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-boundary_disputed', + 'type': 'line', + 'source': 'openmaptiles', + 'source-layer': 'boundary', + 'filter': [ + 'all', + [ + '!=', + ['get', 'maritime'], + 1, + ], + [ + '==', + ['get', 'disputed'], + 1, + ], + ], + 'paint': { + 'line-color': colors.outlineVariant.toHexStringRGB(), + 'line-dasharray': [1, 2], + 'line-width': [ + 'interpolate', + ['linear'], + ['zoom'], + 3, + 1, + 5, + 1.2, + 12, + 3, + ], + }, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': 'osm-waterway_line_label', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'waterway', + 'minzoom': 10, + 'filter': [ + 'match', + ['geometry-type'], + ['LineString', 'MultiLineString'], + true, + false, + ], + 'paint': { + 'text-color': '#74aee9', + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1.5, + }, + 'layout': { + 'symbol-placement': 'line', + 'symbol-spacing': 350, + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Regular'], + 'text-letter-spacing': 0.2, + 'text-max-width': 5, + 'text-size': 14, + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-water_name_line_label', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'water_name', + 'filter': [ + 'match', + ['geometry-type'], + ['LineString', 'MultiLineString'], + true, + false, + ], + 'paint': { + 'text-color': '#495e91', + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1.5, + }, + 'layout': { + 'symbol-placement': 'line', + 'symbol-spacing': 350, + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Regular'], + 'text-letter-spacing': 0.2, + 'text-max-width': 5, + 'text-size': 14, + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_country_2', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'maxzoom': 9, + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'country', + ], + [ + '==', + ['get', 'rank'], + 2, + ], + ], + 'paint': { + 'text-color': colors.onSurface.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Bold'], + 'text-max-width': 6.25, + 'text-size': [ + 'interpolate', + ['linear'], + ['zoom'], + 2, + 9, + 5, + 17, + ], + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_town', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'minzoom': 6, + 'filter': [ + '==', + ['get', 'class'], + 'town', + ], + 'paint': { + 'text-color': colors.onSurface.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': [ + 'step', + ['zoom'], + 'circle_11_black', + 10, + '', + ], + 'icon-optional': false, + 'icon-size': 0.2, + 'text-anchor': 'bottom', + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Regular'], + 'text-max-width': 8, + 'text-size': [ + 'interpolate', + ['exponential', 1.2], + ['zoom'], + 7, + 12, + 11, + 14, + ], + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_state', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'minzoom': 5, + 'maxzoom': 8, + 'filter': [ + '==', + ['get', 'class'], + 'state', + ], + 'paint': { + 'text-color': colors.onSurfaceVariant.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Regular'], + 'text-letter-spacing': 0.2, + 'text-max-width': 9, + 'text-size': [ + 'interpolate', + ['linear'], + ['zoom'], + 5, + 10, + 8, + 14, + ], + 'text-transform': 'uppercase', + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_city', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'minzoom': 3, + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'city', + ], + [ + '!=', + ['get', 'capital'], + 2, + ], + ], + 'paint': { + 'text-color': colors.onSurface.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': [ + 'step', + ['zoom'], + 'circle_11_black', + 9, + '', + ], + 'icon-optional': false, + 'icon-size': 0.4, + 'text-anchor': 'bottom', + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Regular'], + 'text-max-width': 8, + 'text-offset': [0, -0.1], + 'text-size': [ + 'interpolate', + ['exponential', 1.2], + ['zoom'], + 4, + 11, + 7, + 13, + 11, + 18, + ], + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_city_capital', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'minzoom': 3, + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'city', + ], + [ + '==', + ['get', 'capital'], + 2, + ], + ], + 'paint': { + 'text-color': colors.onSurface.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'icon-allow-overlap': true, + 'icon-image': [ + 'step', + ['zoom'], + 'circle_11_black', + 9, + '', + ], + 'icon-optional': false, + 'icon-size': 0.5, + 'text-anchor': 'bottom', + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Bold'], + 'text-max-width': 8, + 'text-offset': [0, -0.2], + 'text-size': [ + 'interpolate', + ['exponential', 1.2], + ['zoom'], + 4, + 12, + 7, + 14, + 11, + 20, + ], + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_country_3', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'minzoom': 2, + 'maxzoom': 9, + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'country', + ], + [ + '>=', + ['get', 'rank'], + 3, + ], + ], + 'paint': { + 'text-color': colors.onSurface.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Bold'], + 'text-max-width': 6.25, + 'text-size': [ + 'interpolate', + ['linear'], + ['zoom'], + 3, + 9, + 7, + 17, + ], + 'visibility': visible ? 'visible' : 'none', + }, + }, + { + 'id': 'osm-label_country_1', + 'type': 'symbol', + 'source': 'openmaptiles', + 'source-layer': 'place', + 'maxzoom': 9, + 'filter': [ + 'all', + [ + '==', + ['get', 'class'], + 'country', + ], + [ + '==', + ['get', 'rank'], + 1, + ], + ], + 'paint': { + 'text-color': colors.onSurface.toHexStringRGB(), + 'text-halo-blur': 1, + 'text-halo-color': colors.outlineVariant.toHexStringRGB(), + 'text-halo-width': 1, + }, + 'layout': { + 'text-field': [ + 'coalesce', + ['get', 'name:nonlatin'], + ['get', 'name'], + ], + 'text-font': ['Noto Sans TC Bold'], + 'text-max-width': 6.25, + 'text-size': [ + 'interpolate', + ['linear'], + ['zoom'], + 1, + 9, + 4, + 17, + ], + 'visibility': visible ? 'visible' : 'none', + }, + }, + ]; + + static Map googleSource() => { + 'google': { + 'type': 'raster', + 'tiles': ['https://mt1.google.com/vt/lyrs=s&hl=zh-TW&x={x}&y={y}&z={z}'], + 'tileSize': 256, + 'attribution': '© Google Maps', + 'maxzoom': 19, + }, + }; + + static List> googleLayers({bool visible = false}) => [ + { + 'id': 'google-raster', + 'type': 'raster', + 'source': 'google', + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + ]; + + static Map exptechSource() => { + 'exptech': { + 'type': 'vector', + 'url': 'https://lb.exptech.dev/api/v1/map/tiles/tiles.json', + 'tileSize': 512, + 'buffer': 64, + }, + }; + + static List> exptechLayers(ColorScheme colors, {bool visible = false}) => [ + { + 'id': BaseMapLayerIds.exptechGlobalFill, + 'type': 'fill', + 'source': 'exptech', + 'source-layer': 'global', + 'paint': {'fill-color': colors.surfaceContainer.toHexStringRGB(), 'fill-opacity': 1}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': BaseMapLayerIds.exptechCountyFill, + 'type': 'fill', + 'source': 'exptech', + 'source-layer': 'city', + 'paint': {'fill-color': colors.surfaceContainerHigh.toHexStringRGB(), 'fill-opacity': 1}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': BaseMapLayerIds.exptechTownFill, + 'type': 'fill', + 'source': 'exptech', + 'source-layer': 'town', + 'paint': {'fill-color': colors.surfaceContainerHigh.toHexStringRGB(), 'fill-opacity': 1}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + { + 'id': BaseMapLayerIds.exptechCountyOutline, + 'type': 'line', + 'source': 'exptech', + 'source-layer': 'city', + 'paint': {'line-color': colors.outline.toHexStringRGB()}, + 'layout': {'visibility': visible ? 'visible' : 'none'}, + }, + ]; + + static Map locationSource() => { + 'user-location': {'type': 'geojson', 'data': GeoJsonBuilder.empty}, + }; + + static Map locationLayer() => { + 'id': 'user-location', + 'type': 'symbol', + 'source': 'user-location', + 'layout': { + 'icon-image': 'gps', + 'icon-size': kSymbolIconSize, + 'icon-allow-overlap': true, + 'icon-ignore-placement': true, + }, + }; +} diff --git a/lib/widgets/shell_wrapper.dart b/lib/widgets/shell_wrapper.dart new file mode 100644 index 000000000..c55f2d5f9 --- /dev/null +++ b/lib/widgets/shell_wrapper.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +import 'package:go_router/go_router.dart'; + +class ShellWrapper extends StatelessWidget { + final Widget child; + + const ShellWrapper(this.child, {super.key}); + + bool _canPop(BuildContext context) { + final lastMatch = GoRouter.of(context).routerDelegate.currentConfiguration.matches.lastOrNull; + + if (lastMatch is ShellRouteMatch) { + return lastMatch.matches.length == 1; + } + + return true; + } + + @override + Widget build(BuildContext context) => PopScope(canPop: _canPop(context), child: child); +} diff --git a/lib/widgets/transitions/forward_back.dart b/lib/widgets/transitions/forward_back.dart deleted file mode 100644 index 2e1b30969..000000000 --- a/lib/widgets/transitions/forward_back.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -const kBackTransition = Interval(0, 0.5, curve: Easing.emphasizedAccelerate); -const kForwardTransition = Interval(0.5, 1, curve: Easing.emphasizedDecelerate); - -class ForwardBackTransitionPage extends CustomTransitionPage { - ForwardBackTransitionPage({required super.child, super.key}) - : super( - transitionDuration: Durations.long4, - reverseTransitionDuration: Durations.long4, - transitionsBuilder: (context, animation, secondaryAnimation, child) { - final forwardSlide = Tween( - begin: const Offset(0.2, 0.0), - end: Offset.zero, - ).chain(CurveTween(curve: kForwardTransition)); - - final backwardSlide = Tween( - begin: Offset.zero, - end: const Offset(-0.2, 0.0), - ).chain(CurveTween(curve: kBackTransition)); - - final fadeIn = Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: kForwardTransition)); - final fadeOut = Tween(begin: 1.0, end: 0.0).chain(CurveTween(curve: kBackTransition)); - - return SlideTransition( - position: forwardSlide.animate(animation), - child: SlideTransition( - position: backwardSlide.animate(secondaryAnimation), - child: FadeTransition( - opacity: fadeIn.animate(animation), - child: FadeTransition(opacity: fadeOut.animate(secondaryAnimation), child: Material(child: child)), - ), - ), - ); - }, - ); -} diff --git a/lib/widgets/transitions/predictive_fade_forward.dart b/lib/widgets/transitions/predictive_fade_forward.dart new file mode 100644 index 000000000..2a5cd11e5 --- /dev/null +++ b/lib/widgets/transitions/predictive_fade_forward.dart @@ -0,0 +1,244 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class PredictiveBackFadeForwardPageTransitionsBuilder extends PageTransitionsBuilder { + /// Creates an instance of a [PageTransitionsBuilder] that matches Android U's + /// predictive back transition. + const PredictiveBackFadeForwardPageTransitionsBuilder(); + + @override + Widget buildTransitions( + PageRoute route, + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) { + return _PredictiveBackGestureDetector( + route: route, + builder: (BuildContext context) { + // Only do a predictive back transition when the user is performing a + // pop gesture. Otherwise, for things like button presses or other + // programmatic navigation, fall back to FadeForwardsPageTransitionsBuilder. + if (route.popGestureInProgress) { + return _PredictiveBackPageTransition( + animation: animation, + secondaryAnimation: secondaryAnimation, + getIsCurrent: () => route.isCurrent, + child: child, + ); + } + + return const FadeForwardsPageTransitionsBuilder().buildTransitions( + route, + context, + animation, + secondaryAnimation, + child, + ); + }, + ); + } +} + +class _PredictiveBackGestureDetector extends StatefulWidget { + const _PredictiveBackGestureDetector({required this.route, required this.builder}); + + final WidgetBuilder builder; + final PredictiveBackRoute route; + + @override + State<_PredictiveBackGestureDetector> createState() => _PredictiveBackGestureDetectorState(); +} + +class _PredictiveBackGestureDetectorState extends State<_PredictiveBackGestureDetector> with WidgetsBindingObserver { + /// True when the predictive back gesture is enabled. + bool get _isEnabled { + return widget.route.isCurrent && widget.route.popGestureEnabled; + } + + /// The back event when the gesture first started. + PredictiveBackEvent? get startBackEvent => _startBackEvent; + PredictiveBackEvent? _startBackEvent; + set startBackEvent(PredictiveBackEvent? startBackEvent) { + if (_startBackEvent != startBackEvent && mounted) { + setState(() { + _startBackEvent = startBackEvent; + }); + } + } + + /// The most recent back event during the gesture. + PredictiveBackEvent? get currentBackEvent => _currentBackEvent; + PredictiveBackEvent? _currentBackEvent; + set currentBackEvent(PredictiveBackEvent? currentBackEvent) { + if (_currentBackEvent != currentBackEvent && mounted) { + setState(() { + _currentBackEvent = currentBackEvent; + }); + } + } + + // Begin WidgetsBindingObserver. + + @override + bool handleStartBackGesture(PredictiveBackEvent backEvent) { + final bool gestureInProgress = !backEvent.isButtonEvent && _isEnabled; + if (!gestureInProgress) { + return false; + } + + widget.route.handleStartBackGesture(progress: 1 - backEvent.progress); + startBackEvent = currentBackEvent = backEvent; + return true; + } + + @override + void handleUpdateBackGestureProgress(PredictiveBackEvent backEvent) { + widget.route.handleUpdateBackGestureProgress(progress: 1 - backEvent.progress); + currentBackEvent = backEvent; + } + + @override + void handleCancelBackGesture() { + widget.route.handleCancelBackGesture(); + startBackEvent = currentBackEvent = null; + } + + @override + void handleCommitBackGesture() { + widget.route.handleCommitBackGesture(); + startBackEvent = currentBackEvent = null; + } + + // End WidgetsBindingObserver. + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return widget.builder(context); + } +} + +/// Android's predictive back page transition. +class _PredictiveBackPageTransition extends StatelessWidget { + const _PredictiveBackPageTransition({ + required this.animation, + required this.secondaryAnimation, + required this.getIsCurrent, + required this.child, + }); + + // These values were eyeballed to match the native predictive back animation + // on a Pixel 2 running Android API 34. + static const double _scaleFullyOpened = 1.0; + static const double _scaleStartTransition = 0.95; + static const double _opacityFullyOpened = 1.0; + static const double _opacityStartTransition = 0.95; + static const double _weightForStartState = 65.0; + static const double _weightForEndState = 35.0; + static const double _screenWidthDivisionFactor = 20.0; + static const double _xShiftAdjustment = 8.0; + + final Animation animation; + final Animation secondaryAnimation; + final ValueGetter getIsCurrent; + final Widget child; + + Widget _secondaryAnimatedBuilder(BuildContext context, Widget? child) { + final double screenWidth = MediaQuery.widthOf(context); + final double xShift = (screenWidth / _screenWidthDivisionFactor) - _xShiftAdjustment; + + final bool isCurrent = getIsCurrent(); + final Tween xShiftTween = isCurrent ? ConstantTween(0) : Tween(begin: xShift, end: 0); + final Animatable scaleTween = + isCurrent + ? ConstantTween(_scaleFullyOpened) + : TweenSequence(>[ + TweenSequenceItem( + tween: Tween(begin: _scaleStartTransition, end: _scaleFullyOpened), + weight: _weightForStartState, + ), + TweenSequenceItem( + tween: Tween(begin: _scaleFullyOpened, end: _scaleFullyOpened), + weight: _weightForEndState, + ), + ]); + final Animatable fadeTween = + isCurrent + ? ConstantTween(_opacityFullyOpened) + : TweenSequence(>[ + TweenSequenceItem( + tween: Tween(begin: _opacityFullyOpened, end: _opacityStartTransition), + weight: _weightForStartState, + ), + TweenSequenceItem( + tween: Tween(begin: _opacityFullyOpened, end: _opacityFullyOpened), + weight: _weightForEndState, + ), + ]); + + return Transform.translate( + offset: Offset(xShiftTween.animate(secondaryAnimation).value, 0), + child: Transform.scale( + scale: scaleTween.animate(secondaryAnimation).value, + child: Opacity(opacity: fadeTween.animate(secondaryAnimation).value, child: child), + ), + ); + } + + Widget _primaryAnimatedBuilder(BuildContext context, Widget? child) { + final double screenWidth = MediaQuery.widthOf(context); + final double xShift = (screenWidth / _screenWidthDivisionFactor) - _xShiftAdjustment; + + final Animatable xShiftTween = TweenSequence(>[ + TweenSequenceItem(tween: Tween(begin: 0.0, end: 0.0), weight: _weightForStartState), + TweenSequenceItem(tween: Tween(begin: xShift, end: 0.0), weight: _weightForEndState), + ]); + final Animatable scaleTween = TweenSequence(>[ + TweenSequenceItem( + tween: Tween(begin: _scaleFullyOpened, end: _scaleFullyOpened), + weight: _weightForStartState, + ), + TweenSequenceItem( + tween: Tween(begin: _scaleStartTransition, end: _scaleFullyOpened), + weight: _weightForEndState, + ), + ]); + final Animatable fadeTween = TweenSequence(>[ + TweenSequenceItem(tween: Tween(begin: 0.0, end: 0.0), weight: _weightForStartState), + TweenSequenceItem( + tween: Tween(begin: _opacityStartTransition, end: _opacityFullyOpened), + weight: _weightForEndState, + ), + ]); + + return Transform.translate( + offset: Offset(xShiftTween.animate(animation).value, 0), + child: Transform.scale( + scale: scaleTween.animate(animation).value, + child: Opacity(opacity: fadeTween.animate(animation).value, child: child), + ), + ); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: secondaryAnimation, + builder: _secondaryAnimatedBuilder, + child: AnimatedBuilder(animation: animation, builder: _primaryAnimatedBuilder, child: child), + ); + } +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 4c19660fa..af8a49964 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,10 +10,8 @@ import awesome_notifications_core import device_info_plus import dynamic_system_colors import firebase_core -import firebase_crashlytics import firebase_messaging import gal -import geolocator_apple import in_app_purchase_storekit import package_info_plus import path_provider_foundation @@ -28,10 +26,8 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) - FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin")) - GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) InAppPurchasePlugin.register(with: registry.registrar(forPlugin: "InAppPurchasePlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) diff --git a/pubspec.lock b/pubspec.lock index c95179260..ad8d81e62 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: de9ecbb3ddafd446095f7e833c853aff2fa1682b017921fe63a833f9d6f0e422 + sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11 url: "https://pub.dev" source: hosted - version: "1.3.54" + version: "1.3.59" analyzer: dependency: transitive description: @@ -50,21 +50,13 @@ packages: source: hosted version: "2.7.0" async: - dependency: transitive + dependency: "direct main" description: name: async sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.dev" source: hosted version: "2.13.0" - autostarter: - dependency: "direct main" - description: - name: autostarter - sha256: "7aac4cbf4fba208eefbcd5046e716b3c86387da82b319b4fc7cb8db0c7153ec3" - url: "https://pub.dev" - source: hosted - version: "0.0.2" awesome_notifications: dependency: "direct main" description: @@ -258,7 +250,7 @@ packages: source: hosted version: "0.3.4+2" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" @@ -358,66 +350,66 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: "017d17d9915670e6117497e640b2859e0b868026ea36bf3a57feb28c3b97debe" + sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5" url: "https://pub.dev" source: hosted - version: "3.13.0" + version: "3.15.2" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "129a34d1e0fb62e2b488d988a1fc26cc15636357e50944ffee2862efe8929b23" + sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37" url: "https://pub.dev" source: hosted - version: "2.22.0" + version: "2.24.1" firebase_crashlytics: dependency: transitive description: name: firebase_crashlytics - sha256: f3fa4a17c2f061b16b2e3ac7aaed889ae954b8952d0fd3e0009a9870cde7bbd2 + sha256: "662ae6443da91bca1fb0be8aeeac026fa2975e8b7ddfca36e4d90ebafa35dde1" url: "https://pub.dev" source: hosted - version: "4.3.5" + version: "4.3.10" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: cedfbe39927711c0e56fc38bfecbd89e17816b21698a3d88d63298c530ed375c + sha256: "7222a8a40077c79f6b8b3f3439241c9f2b34e9ddfde8381ffc512f7b2e61f7eb" url: "https://pub.dev" source: hosted - version: "3.8.5" + version: "3.8.10" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "5f8918848ee0c8eb172fc7698619b2bcd7dda9ade8b93522c6297dd8f9178356" + sha256: "60be38574f8b5658e2f22b7e311ff2064bea835c248424a383783464e8e02fcc" url: "https://pub.dev" source: hosted - version: "15.2.5" + version: "15.2.10" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: "0bbea00680249595fc896e7313a2bd90bd55be6e0abbe8b9a39d81b6b306acb6" + sha256: "685e1771b3d1f9c8502771ccc9f91485b376ffe16d553533f335b9183ea99754" url: "https://pub.dev" source: hosted - version: "4.6.5" + version: "4.6.10" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: ffb392ce2a7e8439cd0a9a80e3c702194e73c927e5c7b4f0adf6faa00b245b17 + sha256: "0d1be17bc89ed3ff5001789c92df678b2e963a51b6fa2bdb467532cc9dbed390" url: "https://pub.dev" source: hosted - version: "3.10.5" + version: "3.10.10" fixnum: dependency: transitive description: @@ -507,38 +499,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.3" - flutter_local_notifications: - dependency: "direct main" - description: - name: flutter_local_notifications - sha256: "33b3e0269ae9d51669957a923f2376bee96299b09915d856395af8c4238aebfa" - url: "https://pub.dev" - source: hosted - version: "19.1.0" - flutter_local_notifications_linux: - dependency: transitive - description: - name: flutter_local_notifications_linux - sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5 - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_local_notifications_platform_interface: - dependency: transitive - description: - name: flutter_local_notifications_platform_interface - sha256: "2569b973fc9d1f63a37410a9f7c1c552081226c597190cb359ef5d5762d1631c" - url: "https://pub.dev" - source: hosted - version: "9.0.0" - flutter_local_notifications_windows: - dependency: transitive - description: - name: flutter_local_notifications_windows - sha256: f8fc0652a601f83419d623c85723a3e82ad81f92b33eaa9bcc21ea1b94773e6e - url: "https://pub.dev" - source: hosted - version: "1.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -552,14 +512,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.7" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: d44bf546b13025ec7353091516f6881f1d4c633993cb109c3916c3a0159dadf1 - url: "https://pub.dev" - source: hosted - version: "2.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -602,6 +554,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + geojson_vi: + dependency: "direct main" + description: + name: geojson_vi + sha256: a47e0efd17617aef8b239719ea2a3ef743563e873709531ee5498ccfd04069f2 + url: "https://pub.dev" + source: hosted + version: "2.2.5" geolocator: dependency: "direct main" description: @@ -838,26 +798,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.1" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lint: dependency: "direct dev" description: @@ -877,10 +837,11 @@ packages: maplibre_gl: dependency: "direct main" description: - name: maplibre_gl - sha256: "5c7b1008396b2a321bada7d986ed60f9423406fbc7bd16f7ce91b385dfa054cd" - url: "https://pub.dev" - source: hosted + path: maplibre_gl + ref: main + resolved-ref: "4876f98336cb811f4722652629d0271ffffcab5f" + url: "https://github.com/maplibre/flutter-maplibre-gl.git" + source: git version: "0.22.0" maplibre_gl_platform_interface: dependency: transitive @@ -994,14 +955,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" path_provider: dependency: "direct main" description: @@ -1090,14 +1043,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.3.0" - permission_handler_windows: - dependency: transitive - description: - name: permission_handler_windows - sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" - url: "https://pub.dev" - source: hosted - version: "0.2.1" petitparser: dependency: transitive description: @@ -1455,14 +1400,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" - tutorial_coach_mark: - dependency: "direct main" - description: - name: tutorial_coach_mark - sha256: "9cdb721165d1cfb6e9b1910a1af1b3570fa6caa5059cf1506fcbd00bf7102abf" - url: "https://pub.dev" - source: hosted - version: "1.3.0" typed_data: dependency: transitive description: @@ -1543,30 +1480,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.1" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" - url: "https://pub.dev" - source: hosted - version: "1.1.18" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" - url: "https://pub.dev" - source: hosted - version: "1.1.16" vector_math: dependency: transitive description: @@ -1664,5 +1577,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.8.0-0 <4.0.0" - flutter: ">=3.31.0-0.0.pre" + dart: ">=3.8.0 <4.0.0" + flutter: ">=3.35.1" diff --git a/pubspec.yaml b/pubspec.yaml index 2dc1c66e6..12446987d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,13 @@ name: dpip description: "Disaster Prevention Information Platform" publish_to: 'none' -version: 3.0.0 +version: 3.1.101 environment: - sdk: '>=3.7.0 <4.0.0' + sdk: '>=3.8.0 <4.0.0' + flutter: '>=3.35.1' dependencies: - autostarter: 0.0.2 awesome_notifications: 0.10.1 awesome_notifications_core: 0.10.1 awesome_notifications_fcm: 0.10.1 @@ -20,8 +20,8 @@ dependencies: url: https://github.com/pvsvamsi/Disable-Battery-Optimizations.git ref: 414b781 dynamic_system_colors: ^1.8.0 - firebase_core: ^3.13.0 - firebase_messaging: 15.2.5 + firebase_core: 3.15.2 #4.0.0 升級最低支援iOS 15 + firebase_messaging: 15.2.10 fl_chart: ^0.71.0 flex_color_picker: ^3.7.0 flutter: @@ -34,7 +34,6 @@ dependencies: flutter_localizations: sdk: flutter flutter_markdown: ^0.7.7 - flutter_svg: ^2.1.0 fluttertoast: 8.2.12 freezed_annotation: ^3.0.0 gal: ^2.3.0 @@ -47,7 +46,11 @@ dependencies: in_app_update: 4.2.3 intl: any json_annotation: 4.9.0 - maplibre_gl: 0.22.0 + maplibre_gl: + git: + url: https://github.com/maplibre/flutter-maplibre-gl.git + path: maplibre_gl + ref: main material_symbols_icons: ^4.2815.0 package_info_plus: ^8.3.0 path_provider: ^2.1.5 @@ -59,10 +62,12 @@ dependencies: styled_text: ^8.1.0 talker_flutter: ^4.7.2 timezone: ^0.10.0 - tutorial_coach_mark: ^1.3.0 url_launcher: ^6.3.1 ip_country_lookup: ^1.0.0 flutter_icmp_ping: ^3.1.3 + geojson_vi: ^2.2.5 + crypto: ^3.0.6 + async: ^2.13.0 dependency_overrides: intl: 0.19.0 @@ -77,16 +82,15 @@ dev_dependencies: lint: ^2.0.0 flutter: - generate: true uses-material-design: true assets: + # localizations - assets/translations/ + # other - assets/map/ - assets/DPIP.png - assets/ExpTech.png + - assets/box.json - assets/location.json - assets/notify_test.json - assets/time.json - - assets/box.json - - assets/sprites.png - - assets/sprites.json diff --git a/tools/update_translations.sh b/tools/update_translations.sh index 6b7d0b331..4340f226c 100755 --- a/tools/update_translations.sh +++ b/tools/update_translations.sh @@ -1,7 +1,11 @@ #!/bin/bash -# 用於更新 .po 檔案與 .pot 檔案中最新翻譯的腳本 +# 用於更新 .pot 檔案與生成 zh-Hant.po 的腳本 # 此腳本應從專案根目錄執行 +# 其他語言的 .po 檔案由 Crowdin 自動同步管理 + +# 設定語言環境為繁體中文 +export LC_ALL=zh_TW.UTF-8 # 檢查終端機是否支援顏色 if [ -t 1 ] && [ -n "$TERM" ] && command -v tput >/dev/null 2>&1; then @@ -16,119 +20,114 @@ else RESET='' fi -# 檢查是否已安裝 msgmerge -if ! command -v msgmerge &> /dev/null; then - echo -e "${RED}msgmerge: command not found${RESET}" - echo - echo -e "${YELLOW}你需要安裝 gettext 套件來更新翻譯檔案。${RESET}" - echo - echo -e "${BLUE}如果你是 macOS 使用者:${RESET}" - echo " brew install gettext" - echo - echo -e "${BLUE}如果你是 Ubuntu/Debian 使用者:${RESET}" - echo " sudo apt-get update && sudo apt-get install gettext" - echo - echo -e "${BLUE}如果你是 Windows 使用者:${RESET}" - echo " choco install gettext # 使用 Chocolatey" - echo " pacman -S gettext # 使用 MSYS2" - echo - exit 1 -fi - # .po 檔案所在目錄 PO_DIR="./assets/translations" -POT_FILE="$PO_DIR/strings.pot" - -# 檢查 .pot 檔案是否存在 -if [ ! -f "$POT_FILE" ]; then - # 執行 i18n 擴充功能匯入器 - echo -e "${BLUE}$ dart run i18n_extension_importer:getstrings --output-file ./assets/translations/strings.pot${RESET}" - dart run i18n_extension_importer:getstrings --output-file ./assets/translations/strings.pot - echo -fi +POT_FILE="./.crowdin/strings.pot" -# 更新每個 .po 檔案 -for po_file in "$PO_DIR"/*.po; do - if [ -f "$po_file" ]; then - echo -e -n "${BLUE}更新 $(basename "$po_file") ${RESET}" - msgmerge --update --backup=off "$po_file" "$POT_FILE" - fi -done +# 執行 i18n 擴充功能匯入器來更新 .pot 檔案 +echo -e "${BLUE}> (1/3) 更新 .pot 檔案...${RESET}" +dart run i18n_extension_importer:getstrings --output-file ./.crowdin/strings.pot +echo -# 更新 zh-Hant.po +# 重新產生 zh-Hant.po(使用固定標頭並直接從 .pot 檔案複製內容) ZH_HANT_PO="$PO_DIR/zh-Hant.po" -if [ -f "$ZH_HANT_PO" ]; then - echo -e "${BLUE}自動填入 zh-Hant.po 的 msgstr...${RESET}" - awk ' - BEGIN { - in_msgid = 0 - in_msgstr = 0 - msgid_content = "" - msgstr_buffer = "" - collecting_msgid = 0 - collecting_msgstr = 0 - } - - # 開始新的 msgid - /^msgid / { - # 處理前一個完整的 msgid/msgstr 對 - if (in_msgid && in_msgstr) { - print "msgid " msgid_content - print "msgstr " msgid_content - } - - # 開始新的 msgid - in_msgid = 1 - in_msgstr = 0 - msgid_content = substr($0, 7) # 提取 msgid 後面的內容 - msgstr_buffer = "" - collecting_msgid = 1 - collecting_msgstr = 0 - next - } - - # 開始 msgstr - /^msgstr / { - collecting_msgid = 0 - collecting_msgstr = 1 - in_msgstr = 1 - msgstr_buffer = $0 - next - } - - # 收集 msgid 或 msgstr 的內容行 - /^"/ { - if (collecting_msgid) { - msgid_content = msgid_content "\n" $0 - } else if (collecting_msgstr) { - msgstr_buffer = msgstr_buffer "\n" $0 - } - next - } - - # 其他行(註解、空行等) - { - if (in_msgid && in_msgstr) { - print "msgid " msgid_content - print "msgstr " msgid_content - } - - # 重置狀態 - in_msgid = 0 - in_msgstr = 0 - msgid_content = "" - msgstr_buffer = "" - collecting_msgid = 0 - collecting_msgstr = 0 - print - } - - END { - # 處理最後一個 msgid/msgstr 對 - if (in_msgid && in_msgstr) { - print "msgid " msgid_content - print "msgstr " msgid_content - } - } - ' "$ZH_HANT_PO" > "$ZH_HANT_PO.tmp" && mv "$ZH_HANT_PO.tmp" "$ZH_HANT_PO" -fi +echo -e "${BLUE}> (2/3) 重新產生 zh-Hant.po...${RESET}" + +# 創建帶有固定標頭的新檔案 +cat > "$ZH_HANT_PO" << 'EOF' +msgid "" +msgstr "" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Crowdin-Project: dpip\n" +"X-Crowdin-Project-ID: 696803\n" +"X-Crowdin-Language: zh-TW\n" +"X-Crowdin-File: /main/.crowdin/strings.pot\n" +"X-Crowdin-File-ID: 20\n" +"Project-Id-Version: dpip\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Language-Team: Chinese Traditional\n" +"Language: zh_TW\n" + +EOF + +# 從 .pot 檔案複製內容並將 msgstr 設為 msgid 的內容 +gawk ' +BEGIN { + collecting_msgid = 0 + msgid_lines = "" + msgid_content = "" +} + +# 註解行直接印出 +/^#/ { print $0; next } + +# 空行直接印出,並重置狀態 +/^$/ { + collecting_msgid = 0 + msgid_lines = "" + msgid_content = "" + print "" + next +} + +# msgid 開始 +/^msgid/ { + collecting_msgid = 1 + msgid_lines = "" + msgid_content = "" + print $0 + + # 單行 msgid + if ($0 ~ /^msgid ".+"$/) { + msgid_content = substr($0, 7) # 去掉 "msgid " 保留引號 + collecting_msgid = 0 + } + next +} + +# 多行 msgid 的續行 +collecting_msgid && /^"/ { + print $0 + if (msgid_lines == "") { + msgid_lines = $0 + } else { + msgid_lines = msgid_lines "\n" $0 + } + next +} + +# msgstr 行 +/^msgstr/ { + collecting_msgid = 0 + + # 單行情況 + if (msgid_content != "") { + print "msgstr " msgid_content + } + # 多行情況 + else if (msgid_lines != "") { + print "msgstr \"\"" + print msgid_lines + } + # 空的情況 + else { + print $0 + } + + msgid_content = "" + msgid_lines = "" + next +} + +# 跳過原本的 msgstr 續行 +/^"/ && !collecting_msgid { next } + +# 其他行直接印出 +{ print $0 } +' "$POT_FILE" >> "$ZH_HANT_PO" + +# 統一路徑格式 +echo -e "${BLUE}> (3/3) 統一路徑格式...${RESET}" +sed -i '' 's|^#: \([^.]\)|#: ./\1|g' "$ZH_HANT_PO" + +echo -e "${BLUE}> 完成!${RESET}"