diff --git a/lang/en-us/components-diy/diy-recommend-code.js b/lang/en-us/components-diy/diy-recommend-code.js new file mode 100644 index 0000000..00bcfc7 --- /dev/null +++ b/lang/en-us/components-diy/diy-recommend-code.js @@ -0,0 +1,83 @@ +export const lang = { + // diy-recommend-code referral code component + // Title + title: 'My Referral Code', + // Share now button + buttonText: 'Share Now', + // Copy code button + copyButtonText: 'Copy Code', + // Get a new code + placeholderRegenerateText: 'Get a New Code', + // Consent description + consentText: 'Your referral code is used to track enterprise registrations via your shared link. We record each application completed through your link for commission settlement.', + // Agree and get code button + consentButtonText: 'Agree & Get Code', + // Login guide tip + loginTipText: 'Log in to view your referral code', + // Log in button + loginBtnText: 'Log In', + // Poster QR tip + posterQrTip: 'Scan to enter and fill in registration info', + // Exclusive code label + exclusiveCode: 'Exclusive Code', + // Code pending label + pendingCode: 'Code Pending', + // Pending + pending: 'Pending', + // Loading code + loading: 'Loading code...', + // Code obtained label + obtainedCode: 'Code Obtained', + // Obtained + obtained: 'Obtained', + // Share invite reward description + shareInviteReward: 'Share with friends and earn rewards for invites', + // Active + activated: '✓ Active', + // Code generated description + codeGenerated: 'Code generated. Use it to invite friends or bind referral for enterprise registration', + // Submitting + submitting: 'Submitting...', + // Share title + shareTitle: 'Inviting you to join the low-altitude economy platform', + // Get failed + getFail: 'Failed to get code. Please retry later', + // Get failed (business code) + getFailCode: 'Failed to get code (business code={code})', + // Get success + getSuccess: 'Obtained', + // Network error + netError: 'Network error. Please retry later', + // Renew code modal title + regenTitle: 'Renew Code', + // Renew code modal content + regenContent: 'After renewal, the old code becomes invalid immediately. All registrations via the old link will no longer be attributed to you. Continue?', + // Confirm renew + regenConfirm: 'Confirm Renew', + // Cancel + regenCancel: 'Cancel', + // Renew failed + regenFail: 'Renewal failed. Please retry later', + // Renew success (old disabled) + regenSuccessOld: 'New code issued. Old code {old} disabled', + // Renew success + regenSuccess: 'Renewed', + // Code not ready yet + codeNotReady: 'Code not ready yet. Please wait', + // Code copied + codeCopied: 'Code copied', + // Copy failed + copyFail: 'Copy failed', + // Copy content is empty + copyEmpty: 'Content is empty', + // Copy after code finishes loading + loadThenCopy: 'Copy after code finishes loading', + // Share link copied + linkCopied: 'Share link copied', + // Poster subtitle + posterShareInvite: 'Share with friends, earn rewards for invites', + // Poster link prefix + posterLinkPrefix: 'Link:', + // Poster link not generated + posterLinkEmpty: '(not generated)', +} diff --git a/lang/en-us/components-diy/diy-webview.js b/lang/en-us/components-diy/diy-webview.js new file mode 100644 index 0000000..0c6a7a9 --- /dev/null +++ b/lang/en-us/components-diy/diy-webview.js @@ -0,0 +1,5 @@ +export const lang = { + // diy-webview webview component + emptyTip: 'Please configure the web link', + loadError: 'Failed to load web page', +} diff --git a/lang/zh-cn/components-diy/diy-recommend-code.js b/lang/zh-cn/components-diy/diy-recommend-code.js new file mode 100644 index 0000000..e13c2df --- /dev/null +++ b/lang/zh-cn/components-diy/diy-recommend-code.js @@ -0,0 +1,83 @@ +export const lang = { + // diy-recommend-code 推荐码组件 + // 标题 + title: '我的推荐码', + // 立即分享按钮 + buttonText: '立即分享', + // 复制推荐码按钮 + copyButtonText: '复制推荐码', + // 换一个新码 + placeholderRegenerateText: '换一个新码', + // 同意说明文案 + consentText: '您的推荐码将用于企业入驻来源追踪,我们会记录每一次通过您分享链接完成的入驻申请,用于您的推广收益结算。', + // 同意并获取推荐码按钮 + consentButtonText: '同意并获取推荐码', + // 未登录引导提示 + loginTipText: '登录后查看我的推荐码', + // 去登录按钮 + loginBtnText: '去登录', + // 海报二维码提示 + posterQrTip: '扫码进入并填写入驻信息', + // 专属推荐码标签 + exclusiveCode: '专属推荐码', + // 待获取推荐码标签 + pendingCode: '待获取推荐码', + // 待获取 + pending: '待获取', + // 推荐码加载中 + loading: '推荐码加载中...', + // 已获得推荐码标签 + obtainedCode: '已获得推荐码', + // 已获得 + obtained: '已获得', + // 分享邀请奖励描述 + shareInviteReward: '分享给好友,邀请注册即可获得奖励', + // 已生效 + activated: '✓ 已生效', + // 推荐码已生成描述 + codeGenerated: '推荐码已生成,可用于邀请好友或企业入驻绑定推荐关系', + // 提交中 + submitting: '提交中...', + // 分享标题 + shareTitle: '邀您入驻低空经济产业平台', + // 获取失败 + getFail: '推荐码获取失败,请稍后重试', + // 获取失败(业务码) + getFailCode: '推荐码获取失败(业务码={code})', + // 获取成功 + getSuccess: '获取成功', + // 网络异常 + netError: '网络异常,请稍后重试', + // 换新码弹窗标题 + regenTitle: '换新码', + // 换新码弹窗内容 + regenContent: '换新码后旧码会立即失效,后续所有使用旧分享链接的入驻申请都不会归属到您,确认继续?', + // 确认换新 + regenConfirm: '确认换新', + // 取消 + regenCancel: '取消', + // 换新失败 + regenFail: '换新失败,请稍后重试', + // 换新成功(旧码停用) + regenSuccessOld: '已换新码,旧码 {old} 已停用', + // 换新成功 + regenSuccess: '换新成功', + // 推荐码还未生成 + codeNotReady: '推荐码还未生成,请稍候', + // 推荐码已复制 + codeCopied: '推荐码已复制', + // 复制失败 + copyFail: '复制失败', + // 复制内容为空 + copyEmpty: '内容为空', + // 推荐码加载完成后再复制 + loadThenCopy: '推荐码加载完成后再复制', + // 推广链接已复制 + linkCopied: '推广链接已复制', + // 海报副标题 + posterShareInvite: '分享给好友,邀请入驻获得奖励', + // 海报链接前缀 + posterLinkPrefix: '链接:', + // 海报链接未生成 + posterLinkEmpty: '(未生成)', +} diff --git a/lang/zh-cn/components-diy/diy-webview.js b/lang/zh-cn/components-diy/diy-webview.js new file mode 100644 index 0000000..d34979f --- /dev/null +++ b/lang/zh-cn/components-diy/diy-webview.js @@ -0,0 +1,5 @@ +export const lang = { + // diy-webview 网页组件 + emptyTip: '请配置网页链接', + loadError: '网页加载失败', +} diff --git a/scripts/i18n_recommend.py b/scripts/i18n_recommend.py new file mode 100644 index 0000000..9e21a8c --- /dev/null +++ b/scripts/i18n_recommend.py @@ -0,0 +1,119 @@ +import re + +path = r"D:\0.daima\lucky_shop\components-diy\diy-recommend-code.vue" +with open(path, "r", encoding="utf-8") as f: + s = f.read() + +BASE = "components-diy.diy-recommend-code." + +# ---- 1. value.xxx || '中文' / nc.xxx || '中文' ---- +TEXT_FIELDS = { + 'title','buttonText','copyButtonText','consentText','consentButtonText', + 'loginTipText','loginBtnText','posterQrTip','placeholderRegenerateText', +} +def repl_value_nc(m): + prefix = m.group(1) # e.g. "value.title || " + field = m.group(2) + if field in TEXT_FIELDS: + return prefix + "$lang('" + BASE + field + "')" + return m.group(0) +s = re.sub(r"((?:value|nc)\.(\w+)\s*\|\|\s*)'([^']*)'", repl_value_nc, s) + +# ---- 2. standalone template text nodes ---- +standalone = { + '\u4e13\u5c5e\u63a8\u8350\u7801': 'exclusiveCode', + '\u5f85\u83b7\u53d6\u63a8\u8350\u7801': 'pendingCode', + '\u5f85\u83b7\u53d6': 'pending', + '\u63a8\u8350\u7801\u52a0\u8f7d\u4e2d...': 'loading', + '\u5df2\u83b7\u5f97\u63a8\u8350\u7801': 'obtainedCode', + '\u5df2\u83b7\u5f97': 'obtained', + '\u5206\u4eab\u7ed9\u597d\u53cb\uff0c\u9080\u8bf7\u6ce8\u518c\u5373\u53ef\u83b7\u5f97\u5956\u52b1': 'shareInviteReward', + '\u2713 \u5df2\u751f\u6548': 'activated', + '\u63a8\u8350\u7801\u5df2\u751f\u6210\uff0c\u53ef\u7528\u4e8e\u9080\u8bf7\u597d\u53cb\u6216\u4f01\u4e1a\u5165\u9a7b\u7ed1\u5b9a\u63a8\u8350\u5173\u7cfb': 'codeGenerated', +} +for zh, key in standalone.items(): + s = s.replace(">%s" % zh, ">{{ $lang('%s%s') }}" % (BASE, key)) + +# ---- 3. '提交中...' standalone in template ternary ---- +s = s.replace("'\u63d0\u4ea4\u4e2d...'", "$lang('%ssubmitting')" % BASE) + +# ---- 4. default() Chinese literals -> '' ---- +default_map = { + "title: '\u6211\u7684\u63a8\u8350\u7801'": "title: ''", + "buttonText: '\u7acb\u5373\u5206\u4eab'": "buttonText: ''", + "copyButtonText: '\u590d\u5236\u63a8\u8350\u7801'": "copyButtonText: ''", + "placeholderRegenerateText: '\u6362\u4e00\u4e2a\u65b0\u7801'": "placeholderRegenerateText: ''", + "consentText: '\u60a8\u7684\u63a8\u8350\u7801\u5c06\u7528\u4e8e\u4f01\u4e1a\u5165\u9a7b\u6765\u6e90\u8ffd\u8e2a\uff0c\u6211\u4eec\u4f1a\u8bb0\u5f55\u6bcf\u4e00\u6b21\u901a\u8fc7\u60a8\u5206\u4eab\u94fe\u63a5\u5b8c\u6210\u7684\u5165\u9a7b\u7533\u8bf7\uff0c\u7528\u4e8e\u60a8\u7684\u63a8\u5e7f\u6536\u76ca\u7ed3\u7b97\u3002'": "consentText: ''", + "consentButtonText: '\u540c\u610f\u5e76\u83b7\u53d6\u63a8\u8350\u7801'": "consentButtonText: ''", + "loginTipText: '\u767b\u5f55\u540e\u67e5\u770b\u6211\u7684\u63a8\u8350\u7801'": "loginTipText: ''", + "loginBtnText: '\u53bb\u767b\u5f55'": "loginBtnText: ''", + "posterQrTip: '\u626b\u7801\u8fdb\u5165\u5e76\u586b\u5199\u5165\u9a7b\u4fe1\u606f'": "posterQrTip: ''", +} +for a, b in default_map.items(): + s = s.replace(a, b) + +# ---- 5. JS user-facing strings ---- +# rcCopyToClipboard util (uses vm.$lang) +s = s.replace("cb && cb(false, '\u5185\u5bb9\u4e3a\u7a7a')", + "cb && cb(false, vm.$lang('%scopyEmpty'))" % BASE) +s = s.replace("fail: () => cb && cb(false, '\u590d\u5236\u5931\u8d25')", + "fail: () => cb && cb(false, vm.$lang('%scopyFail'))" % BASE) +s = s.replace("cb && cb(ok ? true : false, ok ? null : '\u590d\u5236\u5931\u8d25')", + "cb && cb(ok ? true : false, ok ? null : vm.$lang('%scopyFail'))" % BASE) +s = s.replace("cb && cb(false, '\u590d\u5236\u5931\u8d25')", + "cb && cb(false, vm.$lang('%scopyFail'))" % BASE) + +# getFail / getFailCode / getSuccess / netError +s = s.replace("var lastMsg = '\u63a8\u8350\u7801\u83b7\u53d6\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5';", + "var lastMsg = this.$lang('%sgetFail');" % BASE) +s = s.replace("('\u63a8\u8350\u7801\u83b7\u53d6\u5931\u8d25(\u4e1a\u52a1\u7801=' + unpacked.businessCode + ')')", + "this.$lang('%sgetFailCode', { code: unpacked.businessCode })" % BASE) +s = s.replace("uni.showToast({ title: '\u83b7\u53d6\u6210\u529f', icon: 'success' })", + "uni.showToast({ title: this.$lang('%sgetSuccess'), icon: 'success' })" % BASE) +s = s.replace("'\u7f51\u7edc\u5f02\u5e38\uff1a' + failMsg.slice(0, 30)", + "this.$lang('%snetError')" % BASE) +s = s.replace("'\u7f51\u7edc\u5f02\u5e38\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5'", + "this.$lang('%snetError')" % BASE) + +# regen modal +s = s.replace("title: '\u6362\u65b0\u7801',", "title: this.$lang('%sregenTitle')," % BASE) +s = s.replace("content: '\u6362\u65b0\u7801\u540e\u65e7\u7801\u4f1a\u7acb\u5373\u5931\u6548\uff0c\u540e\u7eed\u6240\u6709\u4f7f\u7528\u65e7\u5206\u4eab\u94fe\u63a5\u7684\u5165\u9a7b\u7533\u8bf7\u90fd\u4e0d\u4f1a\u5f52\u5c5e\u5230\u60a8\uff0c\u786e\u8ba4\u7ee7\u7eed\uff1f',", + "content: this.$lang('%sregenContent')," % BASE) +s = s.replace("confirmText: '\u786e\u8ba4\u6362\u65b0',", "confirmText: this.$lang('%sregenConfirm')," % BASE) +s = s.replace("cancelText: '\u53d6\u6d88',", "cancelText: this.$lang('%sregenCancel')," % BASE) +s = s.replace("title: unpacked.msg ? String(unpacked.msg) : '\u6362\u65b0\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5',", + "title: unpacked.msg ? String(unpacked.msg) : this.$lang('%sregenFail')," % BASE) +s = s.replace("title: old ? ('\u5df2\u6362\u65b0\u7801\uff0c\u65e7\u7801 ' + old + ' \u5df2\u505c\u7528') : '\u6362\u65b0\u6210\u529f',", + "title: old ? this.$lang('%sregenSuccessOld', { old: old }) : this.$lang('%sregenSuccess')," % (BASE, BASE)) +s = s.replace("uni.showToast({ title: '\u7f51\u7edc\u5f02\u5e38\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5', icon: 'none' })", + "uni.showToast({ title: this.$lang('%snetError'), icon: 'none' })" % BASE) + +# share title (L1128 specific) then global for the rest +s = s.replace("(vm.nc && (vm.nc.shareTitle || vm.nc.title)) || '\u9080\u60a8\u5165\u9a7b\u4f4e\u7a7a\u7ecf\u6d4e\u4ea7\u4e1a\u5e73\u53f0'", + "(vm.nc && (vm.nc.shareTitle || vm.nc.title)) || this.$lang('%sshareTitle')" % BASE) +s = s.replace("'\u9080\u60a8\u5165\u9a7b\u4f4e\u7a7a\u7ecf\u6d4e\u4ea7\u4e1a\u5e73\u53f0'", + "this.$lang('%sshareTitle')" % BASE) + +# copy / link toasts +s = s.replace("title: ok ? '\u63a8\u8350\u7801\u5df2\u590d\u5236' : (err || '\u590d\u5236\u5931\u8d25')", + "title: ok ? this.$lang('%scodeCopied') : (err || this.$lang('%scopyFail'))" % (BASE, BASE)) +s = s.replace("uni.showToast({ title: '\u63a8\u8350\u7801\u8fd8\u672a\u751f\u6210\uff0c\u8bf7\u7a0d\u5019', icon: 'none' })", + "uni.showToast({ title: this.$lang('%scodeNotReady'), icon: 'none' })" % BASE) +s = s.replace("uni.showToast({ title: '\u63a8\u8350\u7801\u52a0\u8f7d\u5b8c\u6210\u540e\u518d\u590d\u5236', icon: 'none' })", + "uni.showToast({ title: this.$lang('%sloadThenCopy'), icon: 'none' })" % BASE) +s = s.replace("title: ok ? '\u63a8\u5e7f\u94fe\u63a5\u5df2\u590d\u5236' : (err || '\u590d\u5236\u5931\u8d25')", + "title: ok ? this.$lang('%slinkCopied') : (err || this.$lang('%scopyFail'))" % (BASE, BASE)) + +# poster title + canvas +s = s.replace("const title = v.title || '\u6211\u7684\u63a8\u8350\u7801';", + "const title = v.title || this.$lang('%stitle');" % BASE) +s = s.replace("ctx.fillText('\u5206\u4eab\u7ed9\u597d\u53cb,\u9080\u8bf7\u5165\u9a7b\u83b7\u5f97\u5956\u52b1', 24, 70);", + "ctx.fillText(this.$lang('%sposterShareInvite'), 24, 70);" % BASE) +s = s.replace("ctx.fillText('\u94fe\u63a5:' + (linkText || '(\u672a\u751f\u6210)'), 24, urlY);", + "ctx.fillText(this.$lang('%sposterLinkPrefix') + (linkText || this.$lang('%sposterLinkEmpty')), 24, urlY);" % (BASE, BASE)) +s = s.replace("ctx.fillText(v.posterQrTip || '\u626b\u7801\u8fdb\u5165\u5e76\u586b\u5199\u5165\u9a7b\u4fe1\u606f', W / 2, qrY + qrSize + 24);", + "ctx.fillText(v.posterQrTip || this.$lang('%sposterQrTip'), W / 2, qrY + qrSize + 24);" % BASE) + +with open(path, "w", encoding="utf-8") as f: + f.write(s) +print("done")