base for translating the webapp

This commit is contained in:
Light-Wing 2023-06-15 16:55:12 -04:00
parent f544d74c55
commit 8d8258cc9f
16 changed files with 12191 additions and 11094 deletions

10
lingui.config.js Normal file
View File

@ -0,0 +1,10 @@
/** @type {import('@lingui/conf').LinguiConfig} */
module.exports = {
locales: ["en", "ch"],
sourceLocale: "ch",
catalogs: [{
path: "src/locales/{locale}/messages",
include: ["src"]
}],
format: "po"
}

23009
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,29 +3,34 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@babel/runtime": "^7.22.5",
"@lingui/core": "^4.2.1",
"@lingui/react": "^4.2.1",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"jsqr": "^1.3.1",
"medium-zoom": "^1.0.5",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-color": "^2.18.1",
"react-dom": "^16.13.1",
"react-ga": "^3.0.0",
"react-github-btn": "^1.2.0",
"react-indiana-drag-scroll": "^1.6.1",
"react-lazy-load": "^3.0.13",
"react-redux": "^7.2.0",
"react-scripts": "3.4.1",
"redux": "^4.0.5",
"jsqr": "^1.4.0",
"medium-zoom": "^1.0.8",
"prop-types": "^15.8.1",
"react": "^16.14.0",
"react-color": "^2.19.3",
"react-dom": "^16.14.0",
"react-ga": "^3.3.1",
"react-github-btn": "^1.4.0",
"react-indiana-drag-scroll": "^1.8.1",
"react-lazy-load": "^3.1.14",
"react-redux": "^7.2.9",
"react-scripts": "5.0.1",
"redux": "^4.2.1",
"serialize-javascript": "^3.1.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"extract": "lingui extract",
"compile": "lingui compile"
},
"eslintConfig": {
"extends": "react-app"
@ -44,8 +49,10 @@
},
"homepage": "./",
"devDependencies": {
"@lingui/cli": "^4.2.1",
"@lingui/macro": "^4.2.1",
"reactcss": "^1.2.3",
"redux-devtools": "^3.5.0",
"tcb-js-sdk": "^1.6.1"
"redux-devtools": "^3.7.0",
"tcb-js-sdk": "^1.10.10"
}
}

View File

@ -13,6 +13,19 @@ import {loadDownloadData} from "../../actions";
import ReactGA from 'react-ga';
import {setScrollbarWidthProp} from "../../utils/util"
import { i18n } from '@lingui/core'
import { I18nProvider } from '@lingui/react'
import { messages as enMessages } from '../../locales/en/messages'
import { messages as chMessages } from '../../locales/ch/messages'
import LanguageSwitcher from './langSwitcher';
i18n.load({
en: enMessages,
ch: chMessages,
})
i18n.activate('en')
ReactGA.initialize('UA-165845289-1');
ReactGA.addTrackers(
@ -52,12 +65,15 @@ function App({ dispatch }) {
<header className="App-header">
<div className="Layout">
<div className="Qr-outer">
<PartHeader/>
<PartStylesViewer/>
<PartParams/>
<PartDownloadViewer updateDownloadData={updateDownloadData}/>
<PartMore/>
<PartFooter/>
<I18nProvider i18n={i18n}>
<LanguageSwitcher />
<PartHeader />
<PartStylesViewer />
<PartParams />
<PartDownloadViewer updateDownloadData={updateDownloadData} />
<PartMore />
<PartFooter />
</I18nProvider>
</div>
</div>
</header>

View File

@ -2,6 +2,7 @@ import React, {useState} from 'react';
import './App.css';
import PropTypes from 'prop-types';
import {isWeiXin} from "../../utils/navigatorUtils";
import { Trans } from '@lingui/react';
const CountComponent = ({ value }) => {
if (isNaN(value)) return null;
@ -13,8 +14,7 @@ const WxMessage = () => {
if (isWeiXin()) {
return (
<div className="note-font" id="wx-message-inner">
当前客户端不支持下载 SVG<br />
请下载 JPG 并长按二维码保存
<Trans id='WxMessage'>当前客户端不支持下载 SVG,<br /> 请下载 JPG 并长按二维码保存</Trans>
</div>
)
}
@ -42,7 +42,10 @@ const PartDownload = ({ value, downloadCount, onSvgDownload, onImgDownload }) =>
<div className="Qr-Centered title-margin">
<div className="Qr-s-title">Downloads</div>
<p className="Qr-s-subtitle">
<span>下载二维码 {value}</span>
<span>
<Trans id='下载二维码 — '>下载二维码 </Trans>
{value}
</span>
<CountComponent value={downloadCount} />
</p>
</div>

View File

@ -2,13 +2,18 @@ import React from "react";
import '../Qrcode.css';
import InputText from "../../containers/app/InputText";
import QrbtfLogo from "../svg/QrbtfLogo";
import { Trans } from '@lingui/macro';
const PartHeader = () => (
<div className="Qr-Centered">
<div>
<h1 className="Qr-title"><QrbtfLogo className="Qr-title-svg" /></h1>
</div>
<p className="Qr-subtitle">参数化二维码生成器{/* <sup className="Gray">测试版</sup>*/}</p>
<p className="Qr-subtitle">
<Trans id="PartHeader">
参数化二维码生成器
</Trans>
{/* <sup className="Gray">测试版</sup>*/}</p>
<InputText/>
</div>
)

View File

@ -9,7 +9,7 @@ import ImageZoom from "../../containers/app/ImageZoom";
import LinkTrace from "../link/LinkTrace";
import {isPC} from "../../utils/navigatorUtils";
import {handleScroll} from "../../utils/gaHelper";
import { Trans } from "@lingui/macro"
const pictures = [
'https://7172-qrbtf-1d845d-1255694434.tcb.qcloud.la/QrbtfGallery/gallery04.jpg',
'https://7172-qrbtf-1d845d-1255694434.tcb.qcloud.la/QrbtfGallery/gallery02.jpg',
@ -24,11 +24,14 @@ const PartMore = () => {
return (
<div className="Qr-titled-nobg">
<div className="Qr-Centered title-margin">
<Trans >
<div className="Qr-s-title">More</div>
<p className="Qr-s-subtitle">更多</p>
<div className="Qr-s-subtitle Qr-rel">
{isPC() ? <div className="Qr-style-hint">拖拽滑动</div> : null}
</div>
</Trans>
</div>
<div className="title-margin">
<div className="Qr-article">
@ -37,7 +40,10 @@ const PartMore = () => {
data-color-scheme="no-preference: light; light: light; dark: dark;"
data-icon="octicon-star" data-size="large" data-show-count="true"
aria-label="Star ciaochaos/qrbtf on GitHub">Star</GitHubButton></p>
<h2>设计分享</h2>
<h2><Trans>
设计分享
</Trans>
</h2>
</div>
<ScrollContainer
className="Qr-s Qr-s-gallery"

View File

@ -3,12 +3,16 @@ import './App.css';
import ParamListViewer from "../../containers/param/ParamListViewer";
import ParamCorrectLevelViewer from "../../containers/param/ParamCorrectLevelViewer";
import ParamIconViewer from "../../containers/param/disposable/ParamIconViewer";
import { Trans } from '@lingui/macro';
const PartParams = () => (
<div className="Qr-titled-nobg">
<div className="Qr-Centered title-margin">
<div className="Qr-s-title">Parameters</div>
<p className="Qr-s-subtitle">参数调整</p>
<p className="Qr-s-subtitle"><Trans>
参数调整
</Trans>
</p>
</div>
<div className="Qr-Centered">
<div className="Qr-div-table">

View File

@ -0,0 +1,26 @@
import React from 'react';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/macro';
const LanguageSwitcher = () => {
const { i18n } = useLingui();
const handleLanguageChange = (event) => {
const selectedLanguage = event.target.value;
i18n.activate(selectedLanguage);
};
return (
<div>
<label htmlFor="language-select">
<Trans>Select Language:</Trans>
</label>
<select id="language-select" onChange={handleLanguageChange}>
<option value="en">English</option>
<option value="ch">Chinese</option>
</select>
</div>
);
};
export default LanguageSwitcher;

View File

@ -35,11 +35,11 @@ let defaultDrawIcon = function ({ qrcode, params, title, icon }) {
if (icon && iconEnabled) {
const randomIdDefs = getIdNum();
const randomIdClips = getIdNum();
pointList.push(<path d={sq25} stroke="#FFF" strokeWidth={100/iconSize * 1} fill="#FFF" transform={'translate('+String(iconXY)+','+String(iconXY)+') ' + 'scale(' + String(iconSize/100) + ',' + String(iconSize/100) + ')'} />);
pointList.push(<path d={sq25} stroke="#FFF" strokeWidth={100 / iconSize * 1} fill="#FFF" transform={'translate(' + String(iconXY) + ',' + String(iconXY) + ') scale(' + String(iconSize / 100) + ',' + String(iconSize / 100) + ')'} />);
pointList.push(
<g key={id++}>
<defs>
<path id={"defs-path" + randomIdDefs} d={sq25} fill="#FFF" transform={'translate('+String(iconXY)+','+String(iconXY)+') ' + 'scale(' + String(iconSize/100) + ',' + String(iconSize/100) + ')'} /> </defs>
<path id={"defs-path" + randomIdDefs} d={sq25} fill="#FFF" transform={'translate(' + String(iconXY) + ',' + String(iconXY) + ') scale(' + String(iconSize / 100) + ',' + String(iconSize / 100) + ')'} /> </defs>
<clipPath id={"clip-path" + randomIdClips}>
<use xlinkHref={"#defs-path" + randomIdDefs} overflow="visible"/>
</clipPath>
@ -115,16 +115,16 @@ let builtinDrawIcon = function ({ qrcode, params, title, icon }) {
if (icon && iconMode) {
const randomIdDefs = getIdNum();
const randomIdClips = getIdNum();
pointList.push(<path d={sq25} stroke="#FFF" strokeWidth={100/iconSize * 1} fill="#FFF" transform={'translate('+String(iconXY)+','+String(iconXY)+') ' + 'scale(' + String(iconSize/100) + ',' + String(iconSize/100) + ')'} />);
pointList.push(<path d={sq25} stroke="#FFF" strokeWidth={100 / iconSize * 1} fill="#FFF" transform={'translate(' + String(iconXY) + ',' + String(iconXY) + ') scale(' + String(iconSize / 100) + ',' + String(iconSize / 100) + ')'} />);
pointList.push(
<g key={id++}>
<defs>
<path id={"defs-path" + randomIdDefs} d={sq25} fill="#FFF" transform={'translate('+String(iconXY)+','+String(iconXY)+') ' + 'scale(' + String(iconSize/100) + ',' + String(iconSize/100) + ')'} /> </defs>
<path id={"defs-path" + randomIdDefs} d={sq25} fill="#FFF" transform={'translate(' + String(iconXY) + ',' + String(iconXY) + ') scale(' + String(iconSize / 100) + ',' + String(iconSize / 100) + ')'} /> </defs>
<clipPath id={"clip-path" + randomIdClips}>
<use xlinkHref={"#defs-path" + randomIdDefs} overflow="visible"/>
</clipPath>
<g clipPath={"url(#clip-path" + randomIdClips + ")"}>
<g transform={'translate('+String(iconXY)+','+String(iconXY)+') ' + 'scale(' + String(iconSize/100) + ',' + String(iconSize/100) + ')'} >
<g transform={'translate(' + String(iconXY) + ',' + String(iconXY) + ') scale(' + String(iconSize / 100) + ',' + String(iconSize / 100) + ')'} >
{builtinIcon()}
</g>
</g>

View File

@ -4,6 +4,7 @@ import React, {useRef} from "react";
import {isPicture} from "../../utils/imageUtils";
import {decodeData} from "../../utils/qrcodeHandler";
import { handleUpload, handleInputUrl } from "../../utils/gaHelper";
import { Trans } from '@lingui/macro';
const InputText = ({dispatch}) => {
const textRef = useRef();
@ -67,7 +68,9 @@ const InputText = ({dispatch}) => {
/>
</div>
<div className="Qr-input-hint">
上传普通二维码或输入网址
<Trans>
上传普通二维码或输入网址
</Trans>
</div>
</div>
</React.Fragment>);

View File

@ -0,0 +1 @@
/*eslint-disable*/module.exports={messages:JSON.parse("{\"下载二维码 — \":\"下载二维码 — \",\"WxMessage\":\"WxMessage\",\"PartDownload\":\"PartDownload\",\"PartMore1\":[\"<0>More</0><1>更多</1><2>\",[\"0\"],\"</2>\"],\"qINNCJ\":[\"<0>More</0><1>更多</1><2>\",[\"0\"],\"</2>\"],\"ChBdlP\":\"选择语言:\",\"trC0sO\":\"上传普通二维码或输入网址\",\"PartHeader\":\"参数化二维码生成器\",\"MuoWZZ\":\"参数化二维码生成器\",\"PYk7II\":\"参数调整\",\"1R0sTY\":\"设计分享\"}")};

View File

@ -0,0 +1,63 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2023-06-15 15:22-0400\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ch\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#. js-lingui-explicit-id
#: src/components/app/PartDownload.js:46
msgid "下载二维码 — "
msgstr "下载二维码 — "
#. js-lingui-explicit-id
#: src/components/app/PartDownload.js:17
msgid "WxMessage"
msgstr "WxMessage"
#. js-lingui-explicit-id
#: src/components/app/PartDownload.js:45
#~ msgid "PartDownload"
#~ msgstr "PartDownload"
#. js-lingui-explicit-id
#: src/components/app/PartMore.js:27
#~ msgid "PartMore1"
#~ msgstr "<0>More</0><1>更多</1><2>{0}</2>"
#: src/components/app/PartMore.js:27
msgid "<0>More</0><1>更多</1><2>{0}</2>"
msgstr "<0>More</0><1>更多</1><2>{0}</2>"
#: src/components/app/langSwitcher.js:16
msgid "Select Language:"
msgstr "选择语言:"
#: src/containers/app/InputText.js:71
msgid "上传普通二维码或输入网址"
msgstr "上传普通二维码或输入网址"
#. js-lingui-explicit-id
#: src/components/app/PartHeader.js:13
msgid "PartHeader"
msgstr "参数化二维码生成器"
#: src/components/app/PartHeader.js:13
#~ msgid "参数化二维码生成器"
#~ msgstr "参数化二维码生成器"
#: src/components/app/PartParams.js:12
msgid "参数调整"
msgstr "参数调整"
#: src/components/app/PartMore.js:43
msgid "设计分享"
msgstr "设计分享"

View File

@ -0,0 +1 @@
/*eslint-disable*/module.exports={messages:JSON.parse("{\"下载二维码 — \":\"Download QR code —\",\"WxMessage\":\"The current client does not support downloading SVG,<br />Please download JPG and long press the QR code to save\",\"PartDownload\":\"PartDownload\",\"PartMore1\":[\"<0>More</0><1>更多</1><2>\",[\"0\"],\"</2>\"],\"qINNCJ\":[\"<0>More</0><1>More</1><2>\",[\"0\"],\"</2>\"],\"ChBdlP\":\"Select Language:\",\"trC0sO\":\"Upload a common QR code or enter a URL\",\"PartHeader\":\"Parametric QR code generator\",\"MuoWZZ\":\"Parametric QR code generator\",\"PYk7II\":\"Parameter adjustment\",\"1R0sTY\":\"design sharing\"}")};

View File

@ -0,0 +1,53 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2023-06-15 15:21-0400\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#. js-lingui-explicit-id
#: src/components/app/PartDownload.js:46
msgid "下载二维码 — "
msgstr "Download QR code —"
#. js-lingui-explicit-id
#: src/components/app/PartDownload.js:17
msgid "WxMessage"
msgstr "The current client does not support downloading SVG,<br />Please download JPG and long press the QR code to save"
#: src/components/app/PartMore.js:27
msgid "<0>More</0><1>更多</1><2>{0}</2>"
msgstr "<0>More</0><1>More</1><2>{0}</2>"
#: src/components/app/langSwitcher.js:16
msgid "Select Language:"
msgstr "Select Language:"
#: src/containers/app/InputText.js:71
msgid "上传普通二维码或输入网址"
msgstr "Upload a common QR code or enter a URL"
#. js-lingui-explicit-id
#: src/components/app/PartHeader.js:13
msgid "PartHeader"
msgstr "Parametric QR code generator"
#: src/components/app/PartHeader.js:13
#~ msgid "参数化二维码生成器"
#~ msgstr "Parametric QR code generator"
#: src/components/app/PartParams.js:12
msgid "参数调整"
msgstr "Parameter adjustment"
#: src/components/app/PartMore.js:43
msgid "设计分享"
msgstr "design sharing"

View File

@ -0,0 +1,8 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2023-06-15 15:21-0400\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fr\n"