base for translating the webapp
This commit is contained in:
parent
f544d74c55
commit
8d8258cc9f
|
@ -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"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
39
package.json
39
package.json
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
<I18nProvider i18n={i18n}>
|
||||
<LanguageSwitcher />
|
||||
<PartHeader />
|
||||
<PartStylesViewer />
|
||||
<PartParams />
|
||||
<PartDownloadViewer updateDownloadData={updateDownloadData} />
|
||||
<PartMore />
|
||||
<PartFooter />
|
||||
</I18nProvider>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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;
|
|
@ -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>
|
||||
|
|
|
@ -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>);
|
||||
|
|
|
@ -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\":\"设计分享\"}")};
|
|
@ -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 "设计分享"
|
|
@ -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\"}")};
|
|
@ -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"
|
|
@ -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"
|
Loading…
Reference in New Issue