@etsoo/appscript 1.2.56 → 1.2.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -488,19 +488,25 @@ class CoreApp {
488
488
  const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
489
489
  if (isNaN(iterations))
490
490
  return undefined;
491
- const salt = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(2, 34));
492
- const iv = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(34, 66));
493
- const encrypted = messageEncrypted.substring(66);
494
- const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
495
- keySize: 8,
496
- hasher: crypto_js_1.algo.SHA256,
497
- iterations: 1000 * iterations
498
- });
499
- return crypto_js_1.AES.decrypt(encrypted, key, {
500
- iv,
501
- padding: crypto_js_1.pad.Pkcs7,
502
- mode: crypto_js_1.mode.CBC
503
- }).toString(crypto_js_1.enc.Utf8);
491
+ try {
492
+ const salt = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(2, 34));
493
+ const iv = crypto_js_1.enc.Hex.parse(messageEncrypted.substring(34, 66));
494
+ const encrypted = messageEncrypted.substring(66);
495
+ const key = (0, crypto_js_1.PBKDF2)(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
496
+ keySize: 8,
497
+ hasher: crypto_js_1.algo.SHA256,
498
+ iterations: 1000 * iterations
499
+ });
500
+ return crypto_js_1.AES.decrypt(encrypted, key, {
501
+ iv,
502
+ padding: crypto_js_1.pad.Pkcs7,
503
+ mode: crypto_js_1.mode.CBC
504
+ }).toString(crypto_js_1.enc.Utf8);
505
+ }
506
+ catch (e) {
507
+ console.log('decrypt', e);
508
+ return undefined;
509
+ }
504
510
  }
505
511
  /**
506
512
  * Enhanced decrypt message
@@ -516,20 +522,26 @@ class CoreApp {
516
522
  if (pos < 8 || messageEncrypted.length <= 66)
517
523
  return undefined;
518
524
  const timestamp = messageEncrypted.substring(0, pos);
519
- if (durationSeconds != null && durationSeconds > 0) {
520
- const milseconds = shared_1.Utils.charsToNumber(timestamp);
521
- if (isNaN(milseconds) || milseconds < 1)
522
- return undefined;
523
- const timespan = new Date().substract(new Date(milseconds));
524
- if ((durationSeconds <= 12 &&
525
- timespan.totalMonths > durationSeconds) ||
526
- (durationSeconds > 12 &&
527
- timespan.totalSeconds > durationSeconds))
528
- return undefined;
525
+ try {
526
+ if (durationSeconds != null && durationSeconds > 0) {
527
+ const milseconds = shared_1.Utils.charsToNumber(timestamp);
528
+ if (isNaN(milseconds) || milseconds < 1)
529
+ return undefined;
530
+ const timespan = new Date().substract(new Date(milseconds));
531
+ if ((durationSeconds <= 12 &&
532
+ timespan.totalMonths > durationSeconds) ||
533
+ (durationSeconds > 12 &&
534
+ timespan.totalSeconds > durationSeconds))
535
+ return undefined;
536
+ }
537
+ const message = messageEncrypted.substring(pos + 1);
538
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
539
+ return this.decrypt(message, passphrase);
540
+ }
541
+ catch (e) {
542
+ console.log('decryptEnhanced', e);
543
+ return undefined;
529
544
  }
530
- const message = messageEncrypted.substring(pos + 1);
531
- passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
532
- return this.decrypt(message, passphrase);
533
545
  }
534
546
  /**
535
547
  * Detect IP data, call only one time
@@ -29,5 +29,6 @@ export declare class FlutterHost implements IBridgeHost {
29
29
  getStartUrl(): string | null | undefined;
30
30
  loadApp(name: string, startUrl?: string): void;
31
31
  userAuthorization(authorized: boolean): void;
32
+ onUpdate(func: (app: string, version: string) => void): void;
32
33
  }
33
34
  export {};
@@ -86,5 +86,6 @@ class FlutterHost {
86
86
  else
87
87
  this.cacheCommand('userAuthorization', authorized);
88
88
  }
89
+ onUpdate(func) { }
89
90
  }
90
91
  exports.FlutterHost = FlutterHost;
@@ -37,4 +37,9 @@ export interface IBridgeHost {
37
37
  * @param authorized Authorized or not
38
38
  */
39
39
  userAuthorization(authorized: boolean): void;
40
+ /**
41
+ * On update callback
42
+ * @param func Callback function
43
+ */
44
+ onUpdate(func: (app: string, version: string) => void): void;
40
45
  }
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "Are you sure you want to permanently delete this {0}?",
33
33
  "description": "Description",
34
34
  "done": "Done",
35
+ "download": "Download",
35
36
  "edit": "Edit",
36
37
  "email": "Email",
37
38
  "emailAddresses": "Email addresses",
@@ -50,6 +51,7 @@
50
51
  "message": "Message",
51
52
  "mobile": "Mobile number",
52
53
  "mobilePhones": "Mobile numbers",
54
+ "monthLabel": "{0} month(s)",
53
55
  "months": [
54
56
  "Jan.",
55
57
  "Feb.",
@@ -143,6 +145,8 @@
143
145
  "unitJIN": "½Kg",
144
146
  "unitKILOGRAM": "Kg",
145
147
  "update": "Update",
148
+ "updateReady": "Update ready",
149
+ "updateTip": "Restart the application to use the latest features",
146
150
  "user": "User",
147
151
  "view": "View",
148
152
  "warning": "Warning",
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "确定要永久删除此{0}吗?",
33
33
  "description": "描述",
34
34
  "done": "完成",
35
+ "download": "下载",
35
36
  "edit": "修改",
36
37
  "email": "电子邮箱",
37
38
  "emailAddresses": "电子邮箱",
@@ -50,6 +51,7 @@
50
51
  "message": "留言",
51
52
  "mobile": "手机号码",
52
53
  "mobilePhones": "手机号码",
54
+ "monthLabel": "{0}个月",
53
55
  "months": [
54
56
  "1月",
55
57
  "2月",
@@ -144,6 +146,8 @@
144
146
  "unitKILOGRAM": "公斤",
145
147
  "unitTON": "吨",
146
148
  "update": "更新",
149
+ "updateReady": "更新就绪",
150
+ "updateTip": "重新启动应用程序以使用最新功能",
147
151
  "user": "用户",
148
152
  "view": "查看",
149
153
  "warning": "警告",
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "確定要永久刪除此{0}嗎?",
33
33
  "description": "描述",
34
34
  "done": "完成",
35
+ "download": "下載",
35
36
  "edit": "修改",
36
37
  "email": "電子郵箱",
37
38
  "emailAddresses": "電子郵箱",
@@ -50,6 +51,7 @@
50
51
  "message": "留言",
51
52
  "mobilePhone": "手機號碼",
52
53
  "mobilePhones": "手機號碼",
54
+ "monthLabel": "{0}個月",
53
55
  "months": [
54
56
  "1月",
55
57
  "2月",
@@ -143,6 +145,8 @@
143
145
  "unitJIN": "斤",
144
146
  "unitKILOGRAM": "公斤",
145
147
  "update": "更新",
148
+ "updateReady": "更新就緒",
149
+ "updateTip": "重新啟動應用程序以使用最新功能",
146
150
  "user": "用戶",
147
151
  "view": "查看",
148
152
  "warning": "警告",
package/lib/cjs/index.js CHANGED
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -485,19 +485,25 @@ export class CoreApp {
485
485
  const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
486
486
  if (isNaN(iterations))
487
487
  return undefined;
488
- const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
489
- const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
490
- const encrypted = messageEncrypted.substring(66);
491
- const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
492
- keySize: 8,
493
- hasher: algo.SHA256,
494
- iterations: 1000 * iterations
495
- });
496
- return AES.decrypt(encrypted, key, {
497
- iv,
498
- padding: pad.Pkcs7,
499
- mode: mode.CBC
500
- }).toString(enc.Utf8);
488
+ try {
489
+ const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
490
+ const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
491
+ const encrypted = messageEncrypted.substring(66);
492
+ const key = PBKDF2(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, salt, {
493
+ keySize: 8,
494
+ hasher: algo.SHA256,
495
+ iterations: 1000 * iterations
496
+ });
497
+ return AES.decrypt(encrypted, key, {
498
+ iv,
499
+ padding: pad.Pkcs7,
500
+ mode: mode.CBC
501
+ }).toString(enc.Utf8);
502
+ }
503
+ catch (e) {
504
+ console.log('decrypt', e);
505
+ return undefined;
506
+ }
501
507
  }
502
508
  /**
503
509
  * Enhanced decrypt message
@@ -513,20 +519,26 @@ export class CoreApp {
513
519
  if (pos < 8 || messageEncrypted.length <= 66)
514
520
  return undefined;
515
521
  const timestamp = messageEncrypted.substring(0, pos);
516
- if (durationSeconds != null && durationSeconds > 0) {
517
- const milseconds = Utils.charsToNumber(timestamp);
518
- if (isNaN(milseconds) || milseconds < 1)
519
- return undefined;
520
- const timespan = new Date().substract(new Date(milseconds));
521
- if ((durationSeconds <= 12 &&
522
- timespan.totalMonths > durationSeconds) ||
523
- (durationSeconds > 12 &&
524
- timespan.totalSeconds > durationSeconds))
525
- return undefined;
522
+ try {
523
+ if (durationSeconds != null && durationSeconds > 0) {
524
+ const milseconds = Utils.charsToNumber(timestamp);
525
+ if (isNaN(milseconds) || milseconds < 1)
526
+ return undefined;
527
+ const timespan = new Date().substract(new Date(milseconds));
528
+ if ((durationSeconds <= 12 &&
529
+ timespan.totalMonths > durationSeconds) ||
530
+ (durationSeconds > 12 &&
531
+ timespan.totalSeconds > durationSeconds))
532
+ return undefined;
533
+ }
534
+ const message = messageEncrypted.substring(pos + 1);
535
+ passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
536
+ return this.decrypt(message, passphrase);
537
+ }
538
+ catch (e) {
539
+ console.log('decryptEnhanced', e);
540
+ return undefined;
526
541
  }
527
- const message = messageEncrypted.substring(pos + 1);
528
- passphrase = this.encryptionEnhance(passphrase !== null && passphrase !== void 0 ? passphrase : this.passphrase, timestamp);
529
- return this.decrypt(message, passphrase);
530
542
  }
531
543
  /**
532
544
  * Detect IP data, call only one time
@@ -29,5 +29,6 @@ export declare class FlutterHost implements IBridgeHost {
29
29
  getStartUrl(): string | null | undefined;
30
30
  loadApp(name: string, startUrl?: string): void;
31
31
  userAuthorization(authorized: boolean): void;
32
+ onUpdate(func: (app: string, version: string) => void): void;
32
33
  }
33
34
  export {};
@@ -83,4 +83,5 @@ export class FlutterHost {
83
83
  else
84
84
  this.cacheCommand('userAuthorization', authorized);
85
85
  }
86
+ onUpdate(func) { }
86
87
  }
@@ -37,4 +37,9 @@ export interface IBridgeHost {
37
37
  * @param authorized Authorized or not
38
38
  */
39
39
  userAuthorization(authorized: boolean): void;
40
+ /**
41
+ * On update callback
42
+ * @param func Callback function
43
+ */
44
+ onUpdate(func: (app: string, version: string) => void): void;
40
45
  }
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "Are you sure you want to permanently delete this {0}?",
33
33
  "description": "Description",
34
34
  "done": "Done",
35
+ "download": "Download",
35
36
  "edit": "Edit",
36
37
  "email": "Email",
37
38
  "emailAddresses": "Email addresses",
@@ -50,6 +51,7 @@
50
51
  "message": "Message",
51
52
  "mobile": "Mobile number",
52
53
  "mobilePhones": "Mobile numbers",
54
+ "monthLabel": "{0} month(s)",
53
55
  "months": [
54
56
  "Jan.",
55
57
  "Feb.",
@@ -143,6 +145,8 @@
143
145
  "unitJIN": "½Kg",
144
146
  "unitKILOGRAM": "Kg",
145
147
  "update": "Update",
148
+ "updateReady": "Update ready",
149
+ "updateTip": "Restart the application to use the latest features",
146
150
  "user": "User",
147
151
  "view": "View",
148
152
  "warning": "Warning",
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "确定要永久删除此{0}吗?",
33
33
  "description": "描述",
34
34
  "done": "完成",
35
+ "download": "下载",
35
36
  "edit": "修改",
36
37
  "email": "电子邮箱",
37
38
  "emailAddresses": "电子邮箱",
@@ -50,6 +51,7 @@
50
51
  "message": "留言",
51
52
  "mobile": "手机号码",
52
53
  "mobilePhones": "手机号码",
54
+ "monthLabel": "{0}个月",
53
55
  "months": [
54
56
  "1月",
55
57
  "2月",
@@ -144,6 +146,8 @@
144
146
  "unitKILOGRAM": "公斤",
145
147
  "unitTON": "吨",
146
148
  "update": "更新",
149
+ "updateReady": "更新就绪",
150
+ "updateTip": "重新启动应用程序以使用最新功能",
147
151
  "user": "用户",
148
152
  "view": "查看",
149
153
  "warning": "警告",
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "確定要永久刪除此{0}嗎?",
33
33
  "description": "描述",
34
34
  "done": "完成",
35
+ "download": "下載",
35
36
  "edit": "修改",
36
37
  "email": "電子郵箱",
37
38
  "emailAddresses": "電子郵箱",
@@ -50,6 +51,7 @@
50
51
  "message": "留言",
51
52
  "mobilePhone": "手機號碼",
52
53
  "mobilePhones": "手機號碼",
54
+ "monthLabel": "{0}個月",
53
55
  "months": [
54
56
  "1月",
55
57
  "2月",
@@ -143,6 +145,8 @@
143
145
  "unitJIN": "斤",
144
146
  "unitKILOGRAM": "公斤",
145
147
  "update": "更新",
148
+ "updateReady": "更新就緒",
149
+ "updateTip": "重新啟動應用程序以使用最新功能",
146
150
  "user": "用戶",
147
151
  "view": "查看",
148
152
  "warning": "警告",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.2.56",
3
+ "version": "1.2.59",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -54,7 +54,7 @@
54
54
  "dependencies": {
55
55
  "@etsoo/notificationbase": "^1.1.2",
56
56
  "@etsoo/restclient": "^1.0.65",
57
- "@etsoo/shared": "^1.1.12",
57
+ "@etsoo/shared": "^1.1.16",
58
58
  "@types/crypto-js": "^4.1.1",
59
59
  "crypto-js": "^4.1.1"
60
60
  },
@@ -65,13 +65,13 @@
65
65
  "@babel/preset-env": "^7.16.11",
66
66
  "@babel/runtime-corejs3": "^7.17.2",
67
67
  "@types/jest": "^27.4.1",
68
- "@typescript-eslint/eslint-plugin": "^5.12.1",
69
- "@typescript-eslint/parser": "^5.12.1",
68
+ "@typescript-eslint/eslint-plugin": "^5.13.0",
69
+ "@typescript-eslint/parser": "^5.13.0",
70
70
  "eslint": "^8.10.0",
71
71
  "eslint-config-airbnb-base": "^15.0.0",
72
72
  "eslint-plugin-import": "^2.25.4",
73
73
  "jest": "^27.5.1",
74
74
  "ts-jest": "^27.1.3",
75
- "typescript": "^4.5.5"
75
+ "typescript": "^4.6.2"
76
76
  }
77
77
  }
@@ -1143,21 +1143,26 @@ export abstract class CoreApp<
1143
1143
  const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
1144
1144
  if (isNaN(iterations)) return undefined;
1145
1145
 
1146
- const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
1147
- const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
1148
- const encrypted = messageEncrypted.substring(66);
1149
-
1150
- const key = PBKDF2(passphrase ?? this.passphrase, salt, {
1151
- keySize: 8, // 256 / 32
1152
- hasher: algo.SHA256,
1153
- iterations: 1000 * iterations
1154
- });
1155
-
1156
- return AES.decrypt(encrypted, key, {
1157
- iv,
1158
- padding: pad.Pkcs7,
1159
- mode: mode.CBC
1160
- }).toString(enc.Utf8);
1146
+ try {
1147
+ const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
1148
+ const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
1149
+ const encrypted = messageEncrypted.substring(66);
1150
+
1151
+ const key = PBKDF2(passphrase ?? this.passphrase, salt, {
1152
+ keySize: 8, // 256 / 32
1153
+ hasher: algo.SHA256,
1154
+ iterations: 1000 * iterations
1155
+ });
1156
+
1157
+ return AES.decrypt(encrypted, key, {
1158
+ iv,
1159
+ padding: pad.Pkcs7,
1160
+ mode: mode.CBC
1161
+ }).toString(enc.Utf8);
1162
+ } catch (e) {
1163
+ console.log('decrypt', e);
1164
+ return undefined;
1165
+ }
1161
1166
  }
1162
1167
 
1163
1168
  /**
@@ -1180,26 +1185,31 @@ export abstract class CoreApp<
1180
1185
 
1181
1186
  const timestamp = messageEncrypted.substring(0, pos);
1182
1187
 
1183
- if (durationSeconds != null && durationSeconds > 0) {
1184
- const milseconds = Utils.charsToNumber(timestamp);
1185
- if (isNaN(milseconds) || milseconds < 1) return undefined;
1186
- const timespan = new Date().substract(new Date(milseconds));
1187
- if (
1188
- (durationSeconds <= 12 &&
1189
- timespan.totalMonths > durationSeconds) ||
1190
- (durationSeconds > 12 &&
1191
- timespan.totalSeconds > durationSeconds)
1192
- )
1193
- return undefined;
1194
- }
1188
+ try {
1189
+ if (durationSeconds != null && durationSeconds > 0) {
1190
+ const milseconds = Utils.charsToNumber(timestamp);
1191
+ if (isNaN(milseconds) || milseconds < 1) return undefined;
1192
+ const timespan = new Date().substract(new Date(milseconds));
1193
+ if (
1194
+ (durationSeconds <= 12 &&
1195
+ timespan.totalMonths > durationSeconds) ||
1196
+ (durationSeconds > 12 &&
1197
+ timespan.totalSeconds > durationSeconds)
1198
+ )
1199
+ return undefined;
1200
+ }
1195
1201
 
1196
- const message = messageEncrypted.substring(pos + 1);
1197
- passphrase = this.encryptionEnhance(
1198
- passphrase ?? this.passphrase,
1199
- timestamp
1200
- );
1202
+ const message = messageEncrypted.substring(pos + 1);
1203
+ passphrase = this.encryptionEnhance(
1204
+ passphrase ?? this.passphrase,
1205
+ timestamp
1206
+ );
1201
1207
 
1202
- return this.decrypt(message, passphrase);
1208
+ return this.decrypt(message, passphrase);
1209
+ } catch (e) {
1210
+ console.log('decryptEnhanced', e);
1211
+ return undefined;
1212
+ }
1203
1213
  }
1204
1214
 
1205
1215
  /**
@@ -106,4 +106,6 @@ export class FlutterHost implements IBridgeHost {
106
106
  this.host.callHandler('userAuthorization', authorized);
107
107
  else this.cacheCommand('userAuthorization', authorized);
108
108
  }
109
+
110
+ onUpdate(func: (app: string, version: string) => void) {}
109
111
  }
@@ -43,4 +43,10 @@ export interface IBridgeHost {
43
43
  * @param authorized Authorized or not
44
44
  */
45
45
  userAuthorization(authorized: boolean): void;
46
+
47
+ /**
48
+ * On update callback
49
+ * @param func Callback function
50
+ */
51
+ onUpdate(func: (app: string, version: string) => void): void;
46
52
  }
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "Are you sure you want to permanently delete this {0}?",
33
33
  "description": "Description",
34
34
  "done": "Done",
35
+ "download": "Download",
35
36
  "edit": "Edit",
36
37
  "email": "Email",
37
38
  "emailAddresses": "Email addresses",
@@ -50,6 +51,7 @@
50
51
  "message": "Message",
51
52
  "mobile": "Mobile number",
52
53
  "mobilePhones": "Mobile numbers",
54
+ "monthLabel": "{0} month(s)",
53
55
  "months": [
54
56
  "Jan.",
55
57
  "Feb.",
@@ -143,6 +145,8 @@
143
145
  "unitJIN": "½Kg",
144
146
  "unitKILOGRAM": "Kg",
145
147
  "update": "Update",
148
+ "updateReady": "Update ready",
149
+ "updateTip": "Restart the application to use the latest features",
146
150
  "user": "User",
147
151
  "view": "View",
148
152
  "warning": "Warning",
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "确定要永久删除此{0}吗?",
33
33
  "description": "描述",
34
34
  "done": "完成",
35
+ "download": "下载",
35
36
  "edit": "修改",
36
37
  "email": "电子邮箱",
37
38
  "emailAddresses": "电子邮箱",
@@ -50,6 +51,7 @@
50
51
  "message": "留言",
51
52
  "mobile": "手机号码",
52
53
  "mobilePhones": "手机号码",
54
+ "monthLabel": "{0}个月",
53
55
  "months": [
54
56
  "1月",
55
57
  "2月",
@@ -144,6 +146,8 @@
144
146
  "unitKILOGRAM": "公斤",
145
147
  "unitTON": "吨",
146
148
  "update": "更新",
149
+ "updateReady": "更新就绪",
150
+ "updateTip": "重新启动应用程序以使用最新功能",
147
151
  "user": "用户",
148
152
  "view": "查看",
149
153
  "warning": "警告",
@@ -32,6 +32,7 @@
32
32
  "deleteConfirm": "確定要永久刪除此{0}嗎?",
33
33
  "description": "描述",
34
34
  "done": "完成",
35
+ "download": "下載",
35
36
  "edit": "修改",
36
37
  "email": "電子郵箱",
37
38
  "emailAddresses": "電子郵箱",
@@ -50,6 +51,7 @@
50
51
  "message": "留言",
51
52
  "mobilePhone": "手機號碼",
52
53
  "mobilePhones": "手機號碼",
54
+ "monthLabel": "{0}個月",
53
55
  "months": [
54
56
  "1月",
55
57
  "2月",
@@ -143,6 +145,8 @@
143
145
  "unitJIN": "斤",
144
146
  "unitKILOGRAM": "公斤",
145
147
  "update": "更新",
148
+ "updateReady": "更新就緒",
149
+ "updateTip": "重新啟動應用程序以使用最新功能",
146
150
  "user": "用戶",
147
151
  "view": "查看",
148
152
  "warning": "警告",