Skip to content

Commit

Permalink
✨ feat: add i18n support
Browse files Browse the repository at this point in the history
Signed-off-by: SimonShiki <[email protected]>
  • Loading branch information
SimonShiki committed Nov 4, 2023
1 parent b325613 commit 2f5540a
Show file tree
Hide file tree
Showing 11 changed files with 509 additions and 37 deletions.
28 changes: 28 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"app.home.install": "Install",
"app.home.repo": "GitHub Repo",
"app.home.slogan": "Load your Scratch extensions anywhere.",
"app.home.subdescription1": "Chibi loads extensions by directly injecting them into the Scratch virtual machine, which allows you to use your favorite extensions without being restricted by the editor itself.",
"app.home.subdescription2": "Chibi implements the loader independently, which means extensions have a unified implementation standard rather rely on the editor.",
"app.home.subdescription3": "Chibi adds support for non-sandbox extensions and TurboWarp extensions. This means you can seamlessly sideload these extensions into your projects.",
"app.home.subtitle1": "Load ANY Scratch extensions in ANY Scratch-based editors.",
"app.home.subtitle2": "Write once, Run everywhere",
"app.home.subtitle3": "Compatible with most popular extension loading methods",
"app.home.title": "Chibi",
"app.name": "Chibi",
"app.navigation.gallary": "Extension Gallary",
"app.navigation.home": "Home",
"app.navigation.management": "Manage Extension",
"app.navigation.notConnected": "Not Connected",
"app.navigation.settings": "Settings",
"app.navigation.version": "Version:",
"app.settings.extension": "Extension",
"app.settings.extension.dontExposeCtx": "Don't Expose \"Scratch\" Object Globally",
"app.settings.extension.loadFromGallaryOnly": "Load From Gallery's Extensions Only",
"app.settings.extension.noConfirmDialog": "No Confirmation Dialog While Loading Project",
"app.settings.project": "Project",
"app.settings.project.convertProcCall": "Convert Sideload Extension's Blocks Into Procedures Call",
"app.title.gallary": "Extension Gallary",
"app.title.manage": "Manage Extension",
"app.title.settings": "Settings"
}
7 changes: 7 additions & 0 deletions locales/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import en from './en.json';
import zhCN from './zh-cn.json';

export const messages = {
en: en,
'zh-CN': zhCN
};
28 changes: 28 additions & 0 deletions locales/zh-cn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"app.home.install": "安装",
"app.home.repo": "GitHub 仓库",
"app.home.slogan": "全平台的 Scratch 扩展加载器",
"app.home.subdescription1": "Chibi 通过注入 Scratch 虚拟机的方式加载扩展,这意味着你可以使用自己喜欢的扩展,而不受编辑器本身的限制。",
"app.home.subdescription2": "Chibi 独立实现了扩展加载部分,这意味着扩展有了统一的实现标准,而不依赖于编辑器。",
"app.home.subdescription3": "Chibi 增加了对非沙盒扩展和 TurboWarp 扩展的支持。这意味着您可以将这些扩展无缝侧载到您的项目中。",
"app.home.subtitle1": "不讲武德,在任何平台加载你所喜爱的扩展",
"app.home.subtitle2": "一次码,四处行",
"app.home.subtitle3": "兼容主流的扩展加载方式,打破阻碍扩展加载的壁垒",
"app.home.title": "Chibi (琪比)",
"app.name": "Chibi",
"app.navigation.gallary": "扩展橱窗",
"app.navigation.home": "首页",
"app.navigation.management": "扩展管理",
"app.navigation.notConnected": "未连接",
"app.navigation.settings": "设置",
"app.navigation.version": "连接版本:",
"app.settings.extension": "扩展",
"app.settings.extension.dontExposeCtx": "不全局暴露 \"Scratch\" 对象",
"app.settings.extension.loadFromGallaryOnly": "仅允许加载橱窗扩展",
"app.settings.extension.noConfirmDialog": "不确认加载带侧载扩展的项目",
"app.settings.project": "项目",
"app.settings.project.convertProcCall": "将侧载扩展积木转换为自定义积木",
"app.title.gallary": "扩展橱窗",
"app.title.manage": "扩展管理",
"app.title.settings": "设置"
}
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
"start": "vite",
"build": "tsc && vite build",
"lint": "eslint ./src/ --ext .js,.ts,tsx,jsx",
"preview": "vite preview"
"preview": "vite preview",
"extract": "formatjs extract 'src/**/*.{ts,tsx}' --ignore='**/*.d.ts' --out-file locales/en.json --format simple",
"postinstall": "patch-package"
},
"dependencies": {
"@cookbook/solid-intl": "^0.1.2",
"@fontsource/roboto": "^5.0.8",
"@formatjs/cli": "^6.2.1",
"@suid/icons-material": "^0.6.11",
"@suid/material": "^0.15.1",
"solid-js": "^1.7.8"
Expand All @@ -21,6 +25,8 @@
"@typescript-eslint/parser": "^6.7.5",
"eslint": "^8.51.0",
"eslint-plugin-solid": "^0.13.0",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"sharp": "^0.32.6",
"svgo": "^3.0.2",
"typescript": "^5.0.2",
Expand Down
38 changes: 38 additions & 0 deletions patches/@cookbook+solid-intl+0.1.2.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
diff --git a/node_modules/@cookbook/solid-intl/package.json b/node_modules/@cookbook/solid-intl/package.json
index 75735fa..f35ab11 100644
--- a/node_modules/@cookbook/solid-intl/package.json
+++ b/node_modules/@cookbook/solid-intl/package.json
@@ -28,13 +28,28 @@
"exports": {
".": {
"solid": "./dist/source/index.js",
- "import": "./dist/esm/index.js",
+ "import": {
+ "types": "./dist/types/index.d.ts",
+ "default": "./dist/esm/index.js"
+ },
"browser": {
- "import": "./dist/esm/index.js",
- "require": "./dist/cjs/index.cjs"
+ "import": {
+ "types": "./dist/types/index.d.ts",
+ "default": "./dist/esm/index.js"
+ },
+ "require": {
+ "types": "./dist/types/index.d.ts",
+ "default": "./dist/cjs/index.cjs"
+ }
+ },
+ "require": {
+ "default": "./dist/cjs/index.cjs",
+ "types": "./dist/types/index.d.ts"
},
- "require": "./dist/cjs/index.cjs",
- "node": "./dist/cjs/index.cjs"
+ "node": {
+ "default": "./dist/cjs/index.cjs",
+ "types": "./dist/types/index.d.ts"
+ }
}
},
"scripts": {
34 changes: 28 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Home from './home';
import Settings from './settings';
import Gallary from './gallary';
import { createSignal, createEffect, onMount, Show } from 'solid-js';
import { defineMessages, useIntl } from '@cookbook/solid-intl';

export interface ExtensionInfo {
name: string;
Expand Down Expand Up @@ -38,10 +39,30 @@ interface ChibiDispatchedSettings {

type ChibiDispatched = ChibiDispatchedSettings | ChibiDispatchedExtensions | ChibiDispatchedClientInfo;

const messages = defineMessages({
chibi: {
id: 'app.name',
defaultMessage: 'Chibi',
},
manage: {
id: 'app.title.manage',
defaultMessage: 'Manage Extension',
},
gallary: {
id: 'app.title.gallary',
defaultMessage: 'Extension Gallary',
},
settings: {
id: 'app.title.settings',
defaultMessage: 'Settings',
}
});

const subtitleMap = {
manage: 'Manage Extension',
gallary: 'Extension Gallary',
settings: 'Settings'
default: messages.chibi,
manage: messages.manage,
gallary: messages.gallary,
settings: messages.settings
} as const;

const initialHash = window.location.hash.trim().slice(1);
Expand All @@ -51,19 +72,20 @@ function App () {
const [clientInfo, setClientInfo] = createSignal<ClientInfo | null>(null);
const [extensionInfos, setExtensionInfos] = createSignal<ExtensionInfo[]>([]);
const [settings, setSettings] = createSignal<Partial<SettingsInfo>>({});
const intl = useIntl();

createEffect(() => {
window.location.hash = page();
if (page() in subtitleMap) {
document.title = `Chibi | ${subtitleMap[page() as keyof typeof subtitleMap]}`;
document.title = `${intl.formatMessage(messages.chibi)} | ${intl.formatMessage(subtitleMap[page() as keyof typeof subtitleMap])}`;
} else {
document.title = `Chibi`;
document.title = `${intl.formatMessage(messages.chibi)}`;
}
});

onMount(() => {
if (!window.opener) return;
window.addEventListener("message", (event: MessageEvent) => {
window.addEventListener('message', (event: MessageEvent) => {
if (!('type' in event.data)) return;
switch ((event.data as ChibiDispatched).type) {
case 'handshake':
Expand Down
67 changes: 56 additions & 11 deletions src/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {
CardMedia,
Stack
} from '@suid/material';
import { useIntl } from '@cookbook/solid-intl';
import CodeIcon from '@suid/icons-material/Code';

function Home () {
const intl = useIntl();
return (
<Stack
spacing={10}
Expand All @@ -23,22 +25,42 @@ function Home () {
alignItems: 'center'
}}>
<img alt='chibimoth' src='/chibi.png' style={{width: '200px'}} />
<Typography variant='h3' sx={{fontWeight: 500}}>Chibi</Typography>
<Typography variant='subtitle1' color='text.secondary'>Load your Scratch extensions anywhere.</Typography>
<Typography variant='h3' sx={{fontWeight: 500}}>
{intl.formatMessage({
id: 'app.home.title',
defaultMessage: 'Chibi'
})}
</Typography>
<Typography variant='subtitle1' color='text.secondary'>
{intl.formatMessage({
id: 'app.home.slogan',
defaultMessage: 'Load your Scratch extensions anywhere.'
})}
</Typography>
<Stack direction='row' spacing={2} sx={{marginTop: '2rem'}}>
<Button
variant='contained'
onClick={() => {
window.open('https://github.com/SimonShiki/scratch-chibi/releases');
}}
>Install</Button>
>
{intl.formatMessage({
id: 'app.home.install',
defaultMessage: 'Install'
})}
</Button>
<Button
color='secondary'
variant='outlined'
onClick={() => {
window.open('https://github.com/SimonShiki/scratch-chibi');
}}
>GitHub Repo</Button>
>
{intl.formatMessage({
id: 'app.home.repo',
defaultMessage: 'GitHub Repo'
})}
</Button>
</Stack>
</Box>
<Box sx={{
Expand All @@ -48,11 +70,18 @@ function Home () {
textAlign: 'center'
}}>
<Typography variant='h5' sx={{fontWeight: 500}}>
Load ANY Scratch extensions in ANY Scratch-based editors.
{intl.formatMessage({
id: 'app.home.subtitle1',
defaultMessage: 'Load ANY Scratch extensions in ANY Scratch-based editors.',
description: 'Load ANY Scratch extensions in ANY Scratch-based editors.'
})}
</Typography>
<Typography variant='subtitle1' sx={{marginBottom: '1rem'}}>
Chibi loads extensions by directly injecting them into the Scratch virtual machine,
which allows you to use your favorite extensions without being restricted by the editor itself.
{intl.formatMessage({
id: 'app.home.subdescription1',
defaultMessage: 'Chibi loads extensions by directly injecting them into the Scratch virtual machine, which allows you to use your favorite extensions without being restricted by the editor itself.',
description: 'Chibi loads extensions by directly injecting them into the Scratch virtual machine, which allows you to use your favorite extensions without being restricted by the editor itself.'
})}
</Typography>
<Stack direction={{ xs: 'column', sm: 'row' }} sx={{flexFlow: 'wrap', justifyContent: 'center'}}>
<Card sx={{width: '300px', margin: '1rem'}}>
Expand Down Expand Up @@ -96,10 +125,18 @@ function Home () {
textAlign: 'center'
}}>
<Typography variant='h5' sx={{fontWeight: 500}}>
Write once, Run everywhere
{intl.formatMessage({
id: 'app.home.subtitle2',
defaultMessage: 'Write once, Run everywhere',
description: 'Write once, Run everywhere'
})}
</Typography>
<Typography variant='subtitle1' sx={{marginBottom: '1rem'}}>
Chibi implements the loader independently, which means extensions have a unified implementation standard rather rely on the editor.
{intl.formatMessage({
id: 'app.home.subdescription2',
defaultMessage: 'Chibi implements the loader independently, which means extensions have a unified implementation standard rather rely on the editor.',
description: 'Chibi implements the loader independently, which means extensions have a unified implementation standard rather rely on the editor.'
})}
</Typography>
<Card sx={{width: '100%', maxWidth: '400px', marginTop: '1rem'}}>
<CardMedia
Expand All @@ -116,10 +153,18 @@ function Home () {
textAlign: 'center'
}}>
<Typography variant='h5' sx={{fontWeight: 500}}>
Compatible with most popular extension loading methods
{intl.formatMessage({
id: 'app.home.subtitle3',
defaultMessage: 'Compatible with most popular extension loading methods',
description: 'Compatible with most popular extension loading methods'
})}
</Typography>
<Typography variant='subtitle1' sx={{marginBottom: '1rem'}}>
Chibi adds support for non-sandbox extensions and TurboWarp extensions. This means you can seamlessly sideload these extensions into your projects.
{intl.formatMessage({
id: 'app.home.subdescription3',
defaultMessage: 'Chibi adds support for non-sandbox extensions and TurboWarp extensions. This means you can seamlessly sideload these extensions into your projects.',
description: 'Chibi adds support for non-sandbox extensions and TurboWarp extensions. This means you can seamlessly sideload these extensions into your projects.'
})}
</Typography>
</Box>
</Stack>
Expand Down
8 changes: 7 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import { render } from 'solid-js/web';
import { IntlProvider } from '@cookbook/solid-intl';
import './index.css';
import { messages } from '../locales';
import App from './App';

const root = document.getElementById('root');

render(() => <App />, root!);
render(() => (
<IntlProvider locale={navigator.language} messages={messages[navigator.language as keyof typeof messages]}>
<App />
</IntlProvider>
), root!);
Loading

0 comments on commit 2f5540a

Please sign in to comment.